比较烦的线段树

首先询问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.
View Code

 

posted on 2014-07-22 21:12  acphile  阅读(186)  评论(0编辑  收藏  举报