专栏文章

P14447 [ICPC 2025 Xi'an R] Azalea Garden

P14447题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mina4bi6
此快照首次捕获于
2025/12/01 23:03
3 个月前
此快照最后确认于
2025/12/01 23:03
3 个月前
查看原文
此篇为 dmy 比赛复盘。
显然剩下最小可以转为击败最多。
aa 最大的拿出来击败其他的肯定是最优的,不妨令为 ii,如果可以击败 sumsum 个,则答案肯定为 sumsumsum+1sum+1,即这个 ii 也可以被打败,考虑以下情况:
  • ai<bia_i< b_i。则 ii 不能被击败,答案为 sumsum
  • 令不能击败的 aja_j 中的最大值为 AA,如果有 biAb_i\leq A,答案为 sum+1sum+1
  • 再能击败中找出一个序列 kk,其中 iikk 的最后一项,使得对于任意 iibki+1akib_{k_{i+1}}\leq a_{k_i},即前者能击败后者,然后有 b1Ab_1\leq A,这样答案为 sum+1sum+1。 我们思考第三种情况,发现向这种环环紧扣的结构可以转换为若干区间,使得它们的并是一段连续的区间。具体地,把每组 ai,bia_i,b_i 转化为区间 [bi,ai][b_i,a_i],若最后存在其中若干区间的并能完全覆盖 [A,bi][A,b_i],则答案可行。线段树维护即可。
具体地,将值离散化,值域线段树下标为防御值 bb,维护区间中尽量长的并,即可以维护 l,rl,r,如果 rsllsrrs_l\leq ls_r,则左端点可以为 lslls_l,否则取 rr 最大值。特殊地,如果 lsrrsrls_r\ge rs_r,则左端点直接为 lslls_l,不用取 min\min 原因是 rslrs_l 一定不小于 lslls_l。然后我们可以在是指线段树统计,唯一特殊的地方是,当 ai<bia_i<b_i 时,我们在统计 aia_i 不可以击败的会算上自己,而自己本来就不能被击败,故直接返回即可。
CPP
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll MOD=998244353;
// head
const int N=4e5+5,M=2e6+5,INF=2e9;
int a[N],b[N];
int d[M],tot;
struct node{int v,x,y;}que[N];
#define mid ((l+r)>>1)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
multiset<int> S[M];
struct node1{int sum,mx,mn;};
struct Seg_tree
{
    node1 ans[M<<2];
    node1 merge(node1 l,node1 r)
    {
        node1 now;
        now.sum=l.sum+r.sum;
        if(l.mx>=r.mx) now.mx=l.mx,now.mn=l.mn;
        else now.mx=r.mx,now.mn=(l.mx>=r.mn?l.mn:r.mn);
        return now;
    }
    void push_up(int pos)
    {
        ans[pos]=merge(ans[ls(pos)],ans[rs(pos)]);   
    }
    void upd(int pos,int x)
    {
        ans[pos].mx=-INF,ans[pos].mn=INF,ans[pos].sum=S[x].size();
        if(S[x].size()) ans[pos].mx=*S[x].rbegin(),ans[pos].mn=x;
    }
    void build(int pos,int l,int r)
    {
        if(l==r){
            upd(pos,l);
            return ;
        }
        build(ls(pos),l,mid);
        build(rs(pos),mid+1,r);
        push_up(pos);
    }
    void modify(int pos,int l,int r,int x)
    {
        if(l==r) {upd(pos,l);return ;}
        if(x<=mid) modify(ls(pos),l,mid,x);
        else modify(rs(pos),mid+1,r,x);
        push_up(pos);
    }
    node1 query(int pos,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr) return ans[pos];
        if(qr<=mid) return query(ls(pos),l,mid,ql,qr);
        else if(ql>mid) return query(rs(pos),mid+1,r,ql,qr);
        return merge(query(ls(pos),l,mid,ql,qr),query(rs(pos),mid+1,r,ql,qr));
    }
}tree;
int work()
{
    int x=tree.ans[1].mx,y=tree.ans[1].mn;
    if(x==tot) return 1;
    node1 tmp=tree.query(1,1,tot,x+1,tot);
    if(x<y) return tmp.sum;
    if(y<=tmp.mx) return tmp.sum;
    return tmp.sum+1;
}
signed main() 
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n,q;cin>>n>>q;
    for(int i=1;i<=n;i++) {cin>>a[i]>>b[i];d[++tot]=a[i],d[++tot]=b[i];}
    for(int i=1;i<=q;i++) {cin>>que[i].v>>que[i].x>>que[i].y;d[++tot]=que[i].x,d[++tot]=que[i].y;}
    sort(d+1,d+tot+1);tot=unique(d+1,d+tot+1)-d-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(d+1,d+tot+1,a[i])-d,b[i]=lower_bound(d+1,d+tot+1,b[i])-d;
    for(int i=1;i<=q;i++) que[i].x=lower_bound(d+1,d+tot+1,que[i].x)-d,que[i].y=lower_bound(d+1,d+tot+1,que[i].y)-d;
    for(int i=1;i<=n;i++) S[b[i]].insert(a[i]);
    tree.build(1,1,tot);
    cout<<work()<<'\n';
    for(int i=1;i<=q;i++){
        S[b[que[i].v]].erase(S[b[que[i].v]].find(a[que[i].v]));
        tree.modify(1,1,tot,b[que[i].v]);
        a[que[i].v]=que[i].x,b[que[i].v]=que[i].y;
        S[b[que[i].v]].insert(a[que[i].v]);
        tree.modify(1,1,tot,b[que[i].v]);
        cout<<work()<<'\n';
    }
    for(int i=1;i<=n;i++) S[b[i]].clear();
    tot=0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...