BZOJ 1858
1858: [Scoi2010]序列操作
Submit: 2489 Solved: 1228
[Submit][Status][Discuss]
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
Source
Solution
直接用线段树维护
Code
1 #include<stdio.h> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define N 100005 7 using namespace std; 8 int n,m; 9 struct seg 10 { 11 int l1,l0,r1,r0,m1,m0,s1,s0; 12 int l,r; 13 int rev,c,full; 14 }t[N<<2]; 15 void rev(int k) 16 { 17 swap(t[k].l1,t[k].l0); 18 swap(t[k].r1,t[k].r0); 19 swap(t[k].m1,t[k].m0); 20 swap(t[k].s1,t[k].s0); 21 if(t[k].full!=-1)t[k].full^=1; 22 } 23 void color(int k,int v) 24 { 25 t[k].rev=0; 26 int s=t[k].r-t[k].l+1; 27 if(v) 28 { 29 t[k].s0=t[k].m0=t[k].l0=t[k].r0=0; 30 t[k].s1=t[k].m1=t[k].l1=t[k].r1=s; 31 }else 32 { 33 t[k].s0=t[k].m0=t[k].l0=t[k].r0=s; 34 t[k].s1=t[k].m1=t[k].l1=t[k].r1=0; 35 } 36 t[k].full=v; 37 } 38 /* 39 seg merge(seg a,seg b) 40 { 41 seg tmp;tmp.l=a.l;tmp.r=b.r; 42 tmp.rev=0;tmp.c=-1; 43 tmp.l0=a.l0;tmp.l1=a.l1; 44 tmp.r0=b.r0;tmp.r1=b.r1; 45 tmp.m0=max(max(a.m0,b.m0),a.r0+b.l0); 46 tmp.m1=max(max(a.m1,b.m1),a.r1+b.l1); 47 tmp.s0=a.s0+b.s0; 48 tmp.s1=a.s1+b.s1; 49 if(a.full==0)tmp.l0=a.m0+b.l0; 50 else if(a.full==1)tmp.l1=a.m1+b.l1; 51 if(b.full==0)tmp.r0=a.r0+b.m0; 52 else if(b.full==1)tmp.r1=a.r1+b.m1; 53 if(a.full=b.full)tmp.full=a.full; 54 else tmp.full=-1; 55 return tmp; 56 }*/ 57 seg merge(seg a,seg b) 58 { 59 seg tmp;tmp.l=a.l;tmp.r=b.r; 60 tmp.rev=0;tmp.c=-1; 61 tmp.l0=a.l0;tmp.l1=a.l1; 62 tmp.r0=b.r0;tmp.r1=b.r1; 63 tmp.m0=max(max(a.m0,b.m0),a.r0+b.l0); 64 tmp.m1=max(max(a.m1,b.m1),a.r1+b.l1); 65 tmp.s0=a.s0+b.s0; 66 tmp.s1=a.s1+b.s1; 67 if(a.full==0)tmp.l0=a.m0+b.l0; 68 else if(a.full==1)tmp.l1=a.m1+b.l1; 69 if(b.full==0)tmp.r0=b.m0+a.r0; 70 else if(b.full==1)tmp.r1=b.m1+a.r1; 71 if(a.full==b.full)tmp.full=a.full; 72 else tmp.full=-1; 73 return tmp; 74 } 75 void pushup(int k) 76 {t[k]=merge(t[k<<1],t[k<<1|1]);} 77 void pushdown(int k) 78 { 79 if(t[k].l==t[k].r)return; 80 if(t[k].c!=-1) 81 { 82 t[k<<1].c=t[k<<1|1].c=t[k].c; 83 color(k<<1,t[k].c);color(k<<1|1,t[k].c); 84 t[k].c=-1; 85 } 86 if(t[k].rev) 87 { 88 t[k<<1].rev^=1; 89 t[k<<1|1].rev^=1; 90 rev(k<<1);rev(k<<1|1); 91 t[k].rev=0; 92 } 93 } 94 void build(int k,int l,int r) 95 { 96 t[k].l=l;t[k].r=r; 97 t[k].c=-1; 98 if(l==r) 99 { 100 scanf("%d",&t[k].full); 101 if(t[k].full) 102 {t[k].l1=t[k].r1=t[k].m1=t[k].s1=1;} 103 else 104 {t[k].l0=t[k].r0=t[k].m0=t[k].s0=1;} 105 return; 106 } 107 int mid=(l+r)>>1; 108 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 109 pushup(k); 110 } 111 void change(int k,int x,int y,int v) 112 { 113 pushdown(k); 114 int l=t[k].l,r=t[k].r; 115 if(l==x && r==y) 116 { 117 color(k,v); 118 t[k].c=v; 119 return; 120 } 121 int mid=(l+r)>>1; 122 if(mid>=y)change(k<<1,x,y,v); 123 else if(mid<x)change(k<<1|1,x,y,v); 124 else 125 { 126 change(k<<1,x,mid,v); 127 change(k<<1|1,mid+1,y,v); 128 } 129 pushup(k); 130 } 131 void reverse(int k,int x,int y) 132 { 133 pushdown(k); 134 int l=t[k].l,r=t[k].r; 135 if(l==x && r==y) 136 { 137 rev(k); 138 t[k].rev=1; 139 return; 140 } 141 int mid=(l+r)>>1; 142 if(mid>=y)reverse(k<<1,x,y); 143 else if(mid<x)reverse(k<<1|1,x,y); 144 else 145 { 146 reverse(k<<1,x,mid); 147 reverse(k<<1|1,mid+1,y); 148 } 149 pushup(k); 150 } 151 seg ask(int k,int x,int y) 152 { 153 pushdown(k); 154 int l=t[k].l,r=t[k].r; 155 if(l==x && r==y)return t[k]; 156 int mid=(l+r)>>1; 157 if(mid>=y)return ask(k<<1,x,y); 158 else if(mid<x)return ask(k<<1|1,x,y); 159 else return merge(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y)); 160 } 161 int asksum(int k,int x,int y) 162 { 163 pushdown(k); 164 int l=t[k].l,r=t[k].r; 165 if(l==x && r==y)return t[k].s1; 166 int mid=(l+r)>>1; 167 if(mid>=y)return asksum(k<<1,x,y); 168 else if(mid<x)return asksum(k<<1|1,x,y); 169 else return asksum(k<<1,x,mid)+asksum(k<<1|1,mid+1,y); 170 } 171 int main() 172 { 173 scanf("%d%d",&n,&m); 174 build(1,1,n); 175 for(int i=0;i<m;i++) 176 { 177 int f,x,y; 178 scanf("%d%d%d",&f,&x,&y); 179 x++;y++; 180 if(f==0)change(1,x,y,0); 181 if(f==1)change(1,x,y,1); 182 if(f==2)reverse(1,x,y); 183 if(f==3)printf("%d\n",asksum(1,x,y)); 184 if(f==4)printf("%d\n",ask(1,x,y).m1); 185 } 186 // system("pause"); 187 return 0; 188 }