CF817F MEX Queries(线段树上二分)

题意

维护一个01串,一开始全部都是0

3种操作

1.把一个区间都变为1

2.把一个区间都变为0

3.把一个区间的所有数字翻转过来

每次操作完成之后询问区间最小的0的位置

l,r<=10^18

题解

区间操作想到线段树,离散化不用说,l,r太大了。

1,2,3操作非常好维护。

然后在查询中二分查询就好了。

一开始看别的博客说要加1节点和r+1节点不知道为什么。

因为我的查询想的是,查询前面全都是1的区间的长度。后来发现做不了。就乖乖照题解做了。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<map>
  7 using namespace std;
  8 const long long N=150020;
  9 map<long long,long long> mp;
 10 long long b[N*4],n,m,cnt; 
 11 struct ask{
 12     long long l,r;
 13     long long k;
 14 }q[N];
 15 struct tree{
 16     long long l,r,sum,sev,lazy;
 17 }tr[N*40];
 18 void build(long long l,long long r,long long now){
 19     tr[now].l=l;
 20     tr[now].r=r;
 21     tr[now].lazy=-1;
 22     if(l==r)return;
 23     long long mid=(l+r)>>1;
 24     build(l,mid,now*2);
 25     build(mid+1,r,now*2+1);
 26 }
 27 void pushdown(long long now){
 28     long long mid=(tr[now].l+tr[now].r)>>1;
 29     if(tr[now].lazy!=-1){
 30         tr[now*2].lazy=tr[now*2+1].lazy=tr[now].lazy;
 31         tr[now*2].sum=(mid-tr[now].l+1)*tr[now].lazy;
 32         tr[now*2+1].sum=(tr[now].r-mid)*tr[now].lazy;
 33         tr[now*2].sev=tr[now*2+1].sev=0;
 34         tr[now].lazy=-1; 
 35     }
 36     if(tr[now].sev){
 37         tr[now*2].sev^=1;
 38         tr[now*2+1].sev^=1;
 39         tr[now*2].sum=(mid-tr[now].l+1)-tr[now*2].sum;
 40         tr[now*2+1].sum=(tr[now].r-mid)-tr[now*2+1].sum;
 41         tr[now].sev=0;
 42     }
 43 }
 44 void update(long long l,long long r,long long now,long long k){
 45 //    cout<<l<<" "<<r<<" "<<tr[now].l<<" "<<tr[now].r<<" "<<now<<endl;
 46     pushdown(now);
 47     if(tr[now].l==l&&tr[now].r==r){
 48         tr[now].sum=(tr[now].r-tr[now].l+1)*k;
 49         tr[now].lazy=k;
 50         tr[now].sev=0;
 51         return ;
 52     }
 53     long long mid=(tr[now].l+tr[now].r)>>1;
 54     if(l>mid){
 55         update(l,r,now*2+1,k);
 56     }
 57     else if(r<=mid){
 58         update(l,r,now*2,k);
 59     }
 60     else{
 61         update(l,mid,now*2,k);
 62         update(mid+1,r,now*2+1,k);
 63     }
 64     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 65 }
 66 void serve(long long l,long long r,long long now){
 67     pushdown(now);
 68     if(tr[now].l==l&&tr[now].r==r){
 69         tr[now].sum=(tr[now].r-tr[now].l+1)-tr[now].sum;
 70         tr[now].sev^=1;
 71         return;
 72     }
 73     long long mid=(tr[now].l+tr[now].r)>>1;
 74     if(l>mid)serve(l,r,now*2+1);
 75     else if(r<=mid)serve(l,r,now*2);
 76     else{
 77         serve(l,mid,now*2);
 78         serve(mid+1,r,now*2+1);
 79     }
 80     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 81 }
 82 void check(long long now){
 83     if(tr[now].l==tr[now].r){
 84         printf("%lld\n",b[tr[now].l]);
 85         return ;
 86     }
 87     long long mid=(tr[now].l+tr[now].r)>>1;
 88     pushdown(now);
 89     if(tr[now*2].sum<mid-tr[now].l+1)check(now*2);
 90     else return check(now*2+1);
 91 }
 92 int main(){
 93     scanf("%lld",&m);
 94     for(long long i=1;i<=m;i++){
 95         scanf("%lld%lld%lld",&q[i].k,&q[i].l,&q[i].r);
 96         q[i].r++;
 97         b[++cnt]=q[i].l;
 98         b[++cnt]=q[i].r;
 99     }
100     b[++cnt]=1;
101     sort(b+1,b+1+cnt);
102     n=unique(b+1,b+1+cnt)-(b+1);
103     for(long long i=1;i<=n;i++){
104         mp[b[i]]=i;
105     }
106     build(1,n,1);
107     for(long long i=1;i<=m;i++){
108         if(q[i].k==1){
109             update(mp[q[i].l],mp[q[i].r]-1,1,1);
110         }
111         else if(q[i].k==2){
112             update(mp[q[i].l],mp[q[i].r]-1,1,0);
113         }
114         else{
115             serve(mp[q[i].l],mp[q[i].r]-1,1);
116         }
117         check(1);
118     }
119     return 0;
120 }
View Code

 

posted @ 2018-07-31 19:26  Xu-daxia  阅读(618)  评论(0编辑  收藏  举报