Codeforces 817F MEX Queries

题意:对一个维护三种操作:1.将[l..r]中的数全部加入集合中。2.将集合中[l..r]范围内的数删去。3.将集合中在[l..r]中的数删去,并将之前不在集合中的数加入集合

 

考虑到最近线段树总是写爆,我决定在CF上切几道水题练练手,于是找到了这题。。。一开始想了想感觉不太会做,后来发现好像可以离散化后用线段树维护区间1的个数来解决。1就是将[l..r]中的所有数赋值为1,2反之,3就是区间长度-当前1的个数。然后敲了很久,最后惊喜地发现我又特么敲爆了。。。调了好久发现是离散化出了问题。。。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300000+10
typedef long long LL;
struct tree{int sum,tag,flag;}tr[10*MAXN];
int n,pre=1,tot=0,pos[MAXN],opt[MAXN];
LL lp[MAXN],rp[MAXN],num[MAXN],b[MAXN*2];
void pushup(int k){tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;}
void pushdown(int k,int l,int r){
    int mid=(l+r)>>1;
    if(tr[k].tag!=-1){
        tr[k<<1].sum=(mid-l+1)*tr[k].tag;
        tr[k<<1|1].sum=(r-mid)*tr[k].tag;
        tr[k<<1].tag=tr[k<<1|1].tag=tr[k].tag;
        tr[k<<1].flag=tr[k<<1|1].flag=0;
        tr[k].tag=-1;
    }
    if(tr[k].flag){
        tr[k<<1].sum=(mid-l+1)-tr[k<<1].sum;
        tr[k<<1|1].sum=(r-mid)-tr[k<<1|1].sum;
        tr[k<<1].flag^=1;
        tr[k<<1|1].flag^=1;
        tr[k].flag=0;
    }
}
void build(int k,int l,int r){
    tr[k].flag=0;tr[k].tag=-1;
    if(l==r){
        tr[k].sum=0;
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    pushup(k);
}
void cover(int k,int l,int r,int L,int R,int t){
//    printf("%d %d %d\n",k,l,r);
    if(l>=L&&r<=R){
        tr[k].sum=(r-l+1)*t;
        tr[k].tag=t;
        tr[k].flag=0;
        return;
    }
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    if(R<=mid)cover(k<<1,l,mid,L,R,t);
    else if(L>mid)cover(k<<1|1,mid+1,r,L,R,t);
    else cover(k<<1,l,mid,L,R,t),cover(k<<1|1,mid+1,r,L,R,t);
    pushup(k);
}
void roate(int k,int l,int r,int L,int R){
//    printf("%d %d %d\n",k,l,r);
    if(l>=L&&r<=R){
        tr[k].sum=(r-l+1)-tr[k].sum;
        tr[k].flag^=1;
        return;
    }
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    if(R<=mid)roate(k<<1,l,mid,L,R);
    else if(L>mid)roate(k<<1|1,mid+1,r,L,R);
    else roate(k<<1,l,mid,L,R),roate(k<<1|1,mid+1,r,L,R);
    pushup(k);
}
int query(int k,int l,int r){
//    printf("%d %d %d\n",k,l,r);
    if(l==r)return l;
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    if(tr[k<<1].sum<mid-l+1)return query(k<<1,l,mid);
    else return query(k<<1|1,mid+1,r);
    pushup(k);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%I64d%I64d",&opt[i],&lp[i],&rp[i]);
        rp[i]++;
        b[++tot]=num[tot]=lp[i];
        b[++tot]=num[tot]=rp[i];
    }
    num[++tot]=b[tot]=pos[tot]=1;
    sort(b+1,b+tot+1);
    int d=unique(b+1,b+tot+1)-b-1;
    for(int i=1;i<=tot;i++)pos[i]=lower_bound(b+1,b+d+1,num[i])-b;
    build(1,1,d);
    for(int i=1;i<=n;i++){
        int l=pos[i*2-1],r=pos[i*2]-1;
        if(opt[i]==1)cover(1,1,d,l,r,1);
        else if(opt[i]==2)cover(1,1,d,l,r,0);
        else roate(1,1,d,l,r);
        printf("%I64d\n",b[query(1,1,d)]);
    }
    return 0;
}

 

  

posted @ 2017-10-17 19:35  NINGLONG  阅读(251)  评论(0编辑  收藏  举报