1858: [Scoi2010]序列操作
Description
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
Input
输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="">
Output
对于每一个询问操作,输出一行,包括1个数,表示其对应的答案
Sample Input
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
Sample Output
5
2
6
5
2
6
5
HINT
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
线段树维护lx,rx,mx即可,两种标记,如果之前有修改,现在要翻转,那么直接将之前的修改异或即可,
之前有翻转,现在修改,直接修改即可。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 struct tree{ 30 int l,r,lx[2],rx[2],mx[2],sum[2],flag; 31 bool rev; 32 }f[4*maxn]; 33 int n,m,tmx,trx,a[maxn]; 34 void pushup(int x){ 35 for0(i,1){ 36 f[x].sum[i]=f[x<<1].sum[i]+f[x<<1|1].sum[i]; 37 f[x].lx[i]=f[x<<1].lx[i]; 38 if(f[x<<1].lx[i]==f[x<<1].r-f[x<<1].l+1) 39 f[x].lx[i]+=f[x<<1|1].lx[i]; 40 f[x].rx[i]=f[x<<1|1].rx[i]; 41 if(f[x<<1|1].rx[i]==f[x<<1|1].r-f[x<<1|1].l+1) 42 f[x].rx[i]+=f[x<<1].rx[i]; 43 f[x].mx[i]=max(f[x<<1].mx[i],max(f[x<<1|1].mx[i],f[x<<1].rx[i]+f[x<<1|1].lx[i])); 44 } 45 } 46 void update(int x,int c){ 47 f[x].flag=c; 48 for0(i,1){ 49 f[x].sum[i]=f[x].lx[i]=f[x].rx[i]=f[x].mx[i]=c==i?(f[x].r-f[x].l+1):0; 50 } 51 } 52 void solverever(int x){ 53 f[x].rev^=1; 54 swap(f[x].sum[0],f[x].sum[1]); 55 swap(f[x].lx[0],f[x].lx[1]); 56 swap(f[x].mx[0],f[x].mx[1]); 57 swap(f[x].rx[0],f[x].rx[1]); 58 if(f[x].flag!=-1){ 59 f[x].rev=0; 60 f[x].flag^=1; 61 return; 62 } 63 } 64 void pushdown(int x){ 65 if(f[x].flag!=-1){ 66 update(x<<1,f[x].flag);update(x<<1|1,f[x].flag); 67 f[x].flag=-1;f[x].rev=0; 68 } 69 if(f[x].rev){ 70 solverever(x<<1);solverever(x<<1|1); 71 f[x].rev=0; 72 } 73 } 74 void change(int i,int left,int right,int v){ 75 if(f[i].l==left&&f[i].r==right){ 76 update(i,v); 77 return ; 78 } 79 pushdown(i); 80 int mid=(f[i].l+f[i].r)>>1; 81 if(right<=mid)change(i<<1,left,right,v); 82 else if(left>mid)change(i<<1|1,left,right,v); 83 else change(i<<1,left,mid,v),change(i<<1|1,mid+1,right,v); 84 pushup(i); 85 } 86 void rever(int i,int left,int right){ 87 if(f[i].l==left&&f[i].r==right){ 88 solverever(i); 89 return; 90 } 91 pushdown(i); 92 int mid=(f[i].l+f[i].r)>>1; 93 if(right<=mid)rever(i<<1,left,right); 94 else if(left>mid)rever(i<<1|1,left,right); 95 else rever(i<<1,left,mid),rever(i<<1|1,mid+1,right); 96 pushup(i); 97 } 98 int qsum(int i,int left,int right){ 99 if(f[i].l==left&&f[i].r==right)return f[i].sum[1]; 100 pushdown(i); 101 int mid=(f[i].l+f[i].r)>>1; 102 if(right<=mid)return qsum(i<<1,left,right); 103 else if(left>mid)return qsum(i<<1|1,left,right); 104 else return qsum(i<<1,left,mid)+qsum(i<<1|1,mid+1,right); 105 } 106 void query(int i,int left,int right){ 107 if(f[i].l==left&&f[i].r==right){ 108 tmx=max(tmx,max(trx+f[i].lx[1],f[i].mx[1])); 109 if(f[i].sum[1]==f[i].r-f[i].l+1) 110 trx+=f[i].sum[1]; 111 else trx=f[i].rx[1]; 112 return ; 113 } 114 pushdown(i); 115 int mid=(f[i].l+f[i].r)>>1; 116 if(right<=mid)query(i<<1,left,right); 117 else if(left>mid)query(i<<1|1,left,right); 118 else query(i<<1,left,mid),query(i<<1|1,mid+1,right); 119 } 120 void build(int i,int left,int right){ 121 f[i].l=left;f[i].r=right;f[i].flag=-1;f[i].rev=0; 122 if(left==right){ 123 for0(j,1) 124 f[i].lx[j]=f[i].mx[j]=f[i].rx[j]=f[i].sum[j]=a[left]==j?1:0; 125 return ; 126 } 127 int mid=(left+right)>>1; 128 build(i<<1,left,mid);build(i<<1|1,mid+1,right); 129 pushup(i); 130 } 131 int main(){ 132 //freopen("input.txt","r",stdin); 133 //freopen("output.txt","w",stdout); 134 n=read();m=read(); 135 for1(i,n)a[i]=read(); 136 build(1,1,n); 137 while(m--){ 138 int x=read(),l=read()+1,r=read()+1; 139 if(!x)change(1,l,r,0); 140 else if(x==1)change(1,l,r,1); 141 else if(x==2)rever(1,l,r); 142 else if(x==3)printf("%d\n",qsum(1,l,r)); 143 else{ 144 trx=tmx=0; 145 query(1,l,r); 146 printf("%d\n",tmx); 147 } 148 } 149 return 0; 150 }