G. Performance Review(换人 线段树)

http://codeforces.com/problemset/problem/1252/G

题意:

给出n个人,每个人有个唯一的能力值,你是第一个人。现在有m次轮换,将每次将 K i K_i 个能力值较小的换出,塞入 K i K_i 个新的人。

有q次询问,每次更改m次中的某一次的某个人的能力值,问你是否可以生存到最后。

解析:

显然对于人数为 K i K_i 的这次轮换,大于你的人的个数最大为 n K i 1 n-K_i-1 。设定初始值 a [ i ] = ( n K i 1 ) a[i]=-(n-K_i-1)

对于第i次轮换假设换入x个大于你的,那么相当于 [ i + 1 , m ] [i+1,m] 都加上x。

如果某次更改后有一个位置大于0,说明不行。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int maxn=1e5+9;

int n,m,q;
int base;

int a[maxn];
vector<int>V[maxn];

#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)

int mx[maxn<<2];
int laz[maxn<<2];
void build(int rt,int l,int r){
    laz[rt]=0;
    if(l==r){
        mx[rt]=a[l];
        return ;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    mx[rt]=max(mx[ls],mx[rs]);
}
void down(int rt){
    if(laz[rt]){
        int &x=laz[rt];
        laz[ls]+=x;
        laz[rs]+=x;
        mx[ls]+=x;
        mx[rs]+=x;
        x=0;
    }
}
void update(int rt,int l,int r,int L,int R,int v){
    if(l>=L&&r<=R){
        mx[rt]+=v;
        laz[rt]+=v;
        return;
    }
    down(rt);
    if(L<=mid)update(ls,l,mid,L,R,v);
    if(R>mid)update(rs,mid+1,r,L,R,v);
    mx[rt]=max(mx[ls],mx[rs]);
}
int query(int rt,int l,int r,int L,int R){
    if(l>=L&&r<=R){
        return mx[rt];
    }
    down(rt);
    int res=-2e9;
    if(L<=mid)res=query(ls,l,mid,L,R);
    if(R>mid)res=max(res,query(rs,mid+1,r,L,R));
    return res;
}



void debug(int m){
    printf("debug :");
    rep(i,1,m){
        printf("%d ",query(1,1,m,i,i));
    }
    puts("");
}

int main(){
    scanf("%d%d%d",&n,&m,&q);
    scanf("%d",&base);
    rep(i,1,n-1){
        int tmp;scanf("%d",&tmp);
        if(tmp>base)a[1]++;
    }
    int K;
    rep(i,1,m){
        scanf("%d",&K);
        rep(j,1,K){
            int tmp;scanf("%d",&tmp);
            V[i].push_back(tmp);
            if(tmp>base){
                a[i+1]++;
            }
        }
    }
    rep(i,2,m)a[i]+=a[i-1];
    rep(i,1,m)a[i]-=n-V[i].size()-1;
    build(1,1,m);


//    debug(m);

    while(q--){
        int I,J,v;scanf("%d%d%d",&I,&J,&v);
        J--;
        bool s1=0,s2=0;
        if(V[I][J]>base)s1=1;
        if(v>base)s2=1;
        V[I][J]=v;
        if(s1!=s2&&I!=m){
            if(s1){
                update(1,1,m,I+1,m,-1);
            }
            else{
                update(1,1,m,I+1,m,1);
            }
        }
        int Max=query(1,1,m,1,m);
        if(Max>0)puts("0");
        else puts("1");



//        debug(m);

    }
}

发布了723 篇原创文章 · 获赞 314 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/103124150
今日推荐