比较烦的线段树
首先询问3很弱智不说,
询问4以前做过类似的,好像是USACO月赛hotel那题类似,维护lmax,rmax,max三个域就可以了
操作0,操作1也很简单,仔细考虑一下就知道也是可以lazy tag的
重点是操作2,好像数据结构题中翻转总是一个难点
由于翻转影响对询问4影响较大(对询问3基本没什么影响)
我们考虑这次维护六个域lmax0,rmax0,max0,lmax1,rmax1 max1 分别表示在区间内0和1从左起最多连续几个,从右起最多连续几个,区间内最多连续几个
然后我们来考虑操作,首先难想到维护rev域表示区间是否翻转,lazy表示0表示全0,1表示全1,-1表示没有进行覆盖操作
操作0,1对操作2有强制性,只要执行操作0,1,就一定可以直接覆盖之前的操作
然后执行取反操作的时候,如果lazy<>-1 那么对lazy取反(0-->1 1-->0) 否则再对rev取反
1 type node=record 2 l,r,lm1,rm1,m1,lm0,rm0,m0,sum:longint; 3 end; 4 5 var tree:array[0..400010] of node; 6 lazy,a:array[0..400010] of integer; 7 rev:array[0..400010] of boolean; 8 ch,i,n,m,x,y:longint; 9 10 function max(a,b:longint):longint; 11 begin 12 if a>b then exit(a) else exit(b); 13 end; 14 15 function min(a,b:longint):longint; 16 begin 17 if a>b then exit(b) else exit(a); 18 end; 19 20 procedure swap(var a,b:longint); 21 var c:longint; 22 begin 23 c:=a; 24 a:=b; 25 b:=c; 26 end; 27 28 procedure fill1(i:longint); 29 var l,r:longint; 30 begin 31 l:=tree[i].l; 32 r:=tree[i].r; 33 tree[i].sum:=r-l+1; 34 tree[i].lm1:=r-l+1; 35 tree[i].rm1:=r-l+1; 36 tree[i].m1:=r-l+1; 37 tree[i].lm0:=0; 38 tree[i].rm0:=0; 39 tree[i].m0:=0; 40 end; 41 42 procedure fill0(i:longint); 43 var l,r:longint; 44 begin 45 l:=tree[i].l; 46 r:=tree[i].r; 47 tree[i].sum:=0; 48 tree[i].lm0:=r-l+1; 49 tree[i].rm0:=r-l+1; 50 tree[i].m0:=r-l+1; 51 tree[i].lm1:=0; 52 tree[i].rm1:=0; 53 tree[i].m1:=0; 54 end; 55 56 procedure change(i:longint); 57 var l,r:longint; 58 begin 59 l:=tree[i].l; 60 r:=tree[i].r; 61 tree[i].sum:=(r-l+1)-tree[i].sum; 62 swap(tree[i].m1,tree[i].m0); 63 swap(tree[i].lm1,tree[i].lm0); 64 swap(tree[i].rm1,tree[i].rm0); 65 end; 66 67 procedure update(i:longint); //由下向上更新 68 var l,r,m,p:longint; 69 begin 70 l:=tree[i].l; 71 r:=tree[i].r; 72 m:=(l+r) shr 1; 73 tree[i].sum:=tree[i*2].sum+tree[i*2+1].sum; 74 // 1 75 tree[i].lm1:=tree[i*2].lm1; 76 if tree[i*2].lm1=m-l+1 then 77 tree[i].lm1:=tree[i].lm1+tree[i*2+1].lm1; 78 79 tree[i].rm1:=tree[i*2+1].rm1; 80 if tree[i*2+1].rm1=r-m then 81 tree[i].rm1:=tree[i].rm1+tree[i*2].rm1; 82 83 tree[i].m1:=max(tree[i].lm1,tree[i].rm1); 84 p:=max(tree[i*2].rm1+tree[i*2+1].lm1,max(tree[i*2].m1,tree[i*2+1].m1)); 85 tree[i].m1:=max(p,tree[i].m1); 86 // 0 87 tree[i].lm0:=tree[i*2].lm0; 88 if tree[i*2].lm0=m-l+1 then 89 tree[i].lm0:=tree[i].lm0+tree[i*2+1].lm0; 90 91 tree[i].rm0:=tree[i*2+1].rm0; 92 if tree[i*2+1].rm0=r-m then 93 tree[i].rm0:=tree[i].rm0+tree[i*2].rm0; 94 95 tree[i].m0:=max(tree[i].lm0,tree[i].rm0); 96 p:=max(tree[i*2].rm0+tree[i*2+1].lm0,max(tree[i*2].m0,tree[i*2+1].m0)); 97 tree[i].m0:=max(p,tree[i].m0); 98 end; 99 100 procedure pushdown(i:longint); //传递标记 101 begin 102 if lazy[i]<>-1 then 103 begin 104 lazy[i*2]:=lazy[i]; 105 lazy[i*2+1]:=lazy[i]; 106 if lazy[i]=1 then 107 begin 108 fill1(i*2); 109 fill1(i*2+1); 110 end 111 else begin 112 fill0(i*2); 113 fill0(i*2+1); 114 end; 115 lazy[i]:=-1; 116 rev[i]:=false; 117 end; 118 if rev[i] then 119 begin 120 if lazy[i*2]<>-1 then lazy[i*2]:=1-lazy[i*2] 121 else rev[i*2]:=not rev[i*2]; 122 if lazy[i*2+1]<>-1 then lazy[i*2+1]:=1-lazy[i*2+1] 123 else rev[i*2+1]:=not rev[i*2+1]; 124 change(i*2+1); 125 change(i*2); 126 rev[i]:=false; 127 end; 128 end; 129 130 procedure build(i,l,r:longint); 131 var m:longint; 132 begin 133 tree[i].l:=l; 134 tree[i].r:=r; 135 lazy[i]:=-1; 136 if l=r then 137 begin 138 tree[i].sum:=a[l]; 139 if a[l]=1 then 140 begin 141 tree[i].lm1:=1; 142 tree[i].rm1:=1; 143 tree[i].m1:=1; 144 end 145 else begin 146 tree[i].lm0:=1; 147 tree[i].rm0:=1; 148 tree[i].m0:=1; 149 end; 150 end 151 else begin 152 m:=(l+r) shr 1; 153 build(i*2,l,m); 154 build(i*2+1,m+1,r); 155 update(i); 156 end; 157 end; 158 159 procedure work(i,l,r:longint); 160 var m:longint; 161 begin 162 if (x<=l) and (y>=r) then 163 begin 164 if rev[i]=true then rev[i]:=false; 165 lazy[i]:=ch; 166 if ch=1 then fill1(i) 167 else fill0(i); 168 end 169 else begin 170 if (lazy[i]<>-1) or (rev[i]) then pushdown(i); 171 m:=(l+r) shr 1; 172 if x<=m then work(i*2,l,m); 173 if y>=m+1 then work(i*2+1,m+1,r); 174 update(i); 175 end; 176 end; 177 178 procedure reverse(i,l,r:longint); 179 var m:longint; 180 begin 181 if (x<=l) and (y>=r) then 182 begin 183 if lazy[i]<>-1 then lazy[i]:=1-lazy[i] 184 else rev[i]:=not rev[i]; 185 change(i); 186 end 187 else begin 188 if (lazy[i]<>-1) or rev[i] then pushdown(i); 189 m:=(l+r) shr 1; 190 if x<=m then reverse(i*2,l,m); 191 if y>=m+1 then reverse(i*2+1,m+1,r); 192 update(i); 193 end; 194 end; 195 196 function asksum(i,l,r:longint):longint; 197 var m,t:longint; 198 begin 199 if (x<=l) and (y>=r) then exit(tree[i].sum) 200 else begin 201 if (lazy[i]<>-1) or rev[i] then pushdown(i); 202 m:=(l+r) shr 1; 203 t:=0; 204 if (x<=m) then t:=t+asksum(i*2,l,m); 205 if y>=m+1 then t:=t+asksum(i*2+1,m+1,r); 206 update(i); 207 exit(t); 208 end; 209 end; 210 211 function askmax(i,l,r:longint):longint; 212 var m,t,t1,t2:longint; 213 begin 214 if (x<=l) and (y>=r) then exit(tree[i].m1) 215 else begin 216 if (lazy[i]<>-1) or rev[i] then pushdown(i); 217 m:=(l+r) shr 1; 218 t1:=0; 219 t2:=0; 220 t:=0; 221 if (x<=m) then t1:=askmax(i*2,l,m); 222 if y>=m+1 then t2:=askmax(i*2+1,m+1,r); 223 if (x<=m) and (y>=m+1) then t:=min(tree[i*2].rm1,m-x+1)+min(tree[i*2+1].lm1,y-m); //注意不能少考虑这种情况 224 t:=max(t,max(t1,t2)); 225 update(i); 226 exit(t); 227 end; 228 end; 229 230 begin 231 readln(n,m); 232 for i:=1 to n do 233 read(a[i]); 234 build(1,1,n); //初始化 235 for i:=1 to m do 236 begin 237 readln(ch,x,y); 238 inc(x); 239 inc(y); 240 if ch=0 then 241 work(1,1,n) 242 else if ch=1 then 243 work(1,1,n) 244 else if ch=2 then 245 reverse(1,1,n) 246 else if ch=3 then 247 writeln(asksum(1,1,n)) 248 else if ch=4 then 249 writeln(askmax(1,1,n)); 250 end; 251 end.