bzoj 1251: 序列终结者 2011-12-20

1251: 序列终结者Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 650  Solved: 277
[Submit][Status][Discuss]Description 网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。Input第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。Output对于每个第3种操作,给出 正确的回答。Sample Input4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4

Sample Output2
【数据范围】
N<=50000,M<=100000。

 

___________________________________________

那个,八中,有点坑,程序也有点坑,所以只好把外挂都开启了。

 

___________________________________________

  1 Program Stone;
  2 
  3 {$inline on}
  4 
  5 {$A+,B-,D-,E-,F-,G+,I-,L-,N+,O-,P+,Q-,R-,S-,T-,V-,X+,Y-}
  6 
  7 {$M 65520,0,655360}
  8 
  9 var i,j,k,n,m,root,lx,rx,v,qu:longint;
 10 
 11     a,lc,rc,f,o,bi,q:array[0..100000]of longint;
 12 
 13     c:array[0..100000]of boolean; //是否翻转,即是否交换左右孩子
 14 
 15  
 16 
 17  Procedure built(x,y:longint);inline;//先建树,一棵比较平衡的树!
 18 
 19  var i,k:longint;
 20 
 21   begin
 22 
 23     k:=(x+y)div 2; //k为根节点,小于k的为左子树,大于k的为右子树。
 24 
 25     q[k]:=y-x+1;
 26 
 27     if y=x then exit;
 28 
 29     if x<=k-1 then begin
 30 
 31                     built(x,k-1);
 32 
 33                     i:=(x+k-1)div 2;
 34 
 35                     f[i]:=k;lc[k]:=i;
 36 
 37                    end;
 38 
 39     if y>=k+1 then begin
 40 
 41                     built(k+1,y);
 42 
 43                     i:=(y+k+1)div 2;
 44 
 45                     f[i]:=k;rc[k]:=i;
 46 
 47                    end;
 48 
 49   end;
 50 
 51  procedure Tonext(x:longint);inline; //将节点的状态传递给子节点
 52 
 53  var i,j:longint;
 54 
 55   begin
 56 
 57    inc(a[x],o[x]);
 58 
 59    if (lc[x]>1)and(lc[x]<n+2) then begin //判断孩子节点是否在整段序列中
 60 
 61                                       inc(o[lc[x]],o[x]);
 62 
 63                                       inc(bi[lc[x]],o[x]);
 64 
 65                                       c[lc[x]]:=c[lc[x]]xor c[x];
 66 
 67                                    end;
 68 
 69    if (rc[x]>1)and(rc[x]<n+2) then begin
 70 
 71                                       inc(o[rc[x]],o[x]);
 72 
 73                                       inc(bi[rc[x]],o[x]);
 74 
 75                                       c[rc[x]]:=c[rc[x]]xor c[x];
 76 
 77                                    end;
 78 
 79    if c[x] then begin //如果需要翻转,就交换左右孩子。
 80 
 81                  i:=lc[x];lc[x]:=rc[x];rc[x]:=i;
 82 
 83                 end;
 84 
 85    o[x]:=0; //修改状态
 86 
 87    c[x]:=false;
 88 
 89   end;
 90 
 91  
 92 
 93  function max(a,b,c:longint):longint;inline;
 94 
 95   begin
 96 
 97    if a>b then max:=a else max:=b;
 98 
 99    if c>max then max:=c;
100 
101   end;
102 
103  
104 
105  procedure change(x:longint);inline; //旋转时改变记录,q为以该节点为根的树有多少个节点。bi为这棵树中的最大值。
106 
107   begin
108 
109     q[x]:=q[lc[x]]+q[rc[x]]+1;
110 
111     bi[x]:=max(bi[lc[x]],bi[rc[x]],a[x])+o[x];
112 
113   end;
114 
115  
116 
117  procedure rightturn(x:longint);inline; //右旋
118 
119  var i,j,k:longint;
120 
121   begin
122 
123     k:=f[x];
124 
125     if k=lc[f[k]] then lc[f[k]]:=x else rc[f[k]]:=x;
126 
127     f[x]:=f[k];
128 
129     lc[k]:=rc[x];f[lc[k]]:=k;
130 
131     rc[x]:=k;f[k]:=x;
132 
133     change(k);
134 
135   end;
136 
137  
138 
139  procedure leftturn(x:longint); inline; //左旋
140 
141  var i,j,k:longint;
142 
143   begin
144 
145     k:=f[x];
146 
147     if k=lc[f[k]] then lc[f[k]]:=x else rc[f[k]]:=x;
148 
149     f[x]:=f[k];
150 
151     rc[k]:=lc[x];f[rc[k]]:=k;
152 
153     lc[x]:=k;f[k]:=x;
154 
155     change(k);
156 
157   end;
158 
159  
160 
161  Procedure splay(x,root:longint);inline; //splay
162 
163  var i,j,k:longint;
164 
165   begin
166 
167    if x=root then exit;
168 
169    while f[x]<>root do
170 
171     begin
172 
173       k:=f[x];
174 
175       if x=lc[k] then begin
176 
177                         if f[k]=root then rightturn(x)
178 
179                                      else if k=lc[f[k]] then begin
180 
181                                                                rightturn(k);
182 
183                                                                rightturn(x);
184 
185                                                              end
186 
187                                                         else begin
188 
189                                                                rightturn(x);
190 
191                                                                leftturn(x);
192 
193                                                              end;
194 
195                       end
196 
197                  else begin
198 
199                         if f[k]=root then leftturn(x)
200 
201                                      else if k=rc[f[k]] then begin
202 
203                                                                leftturn(k);
204 
205                                                                leftturn(x);
206 
207                                                              end
208 
209                                                         else begin
210 
211                                                                leftturn(x);
212 
213                                                                rightturn(x);
214 
215                                                              end;
216 
217                       end;
218 
219     end;
220 
221    change(x);
222 
223   end;
224 
225  
226 
227  procedure toroot(x:longint);inline; //更新父亲节点,直到根为止
228 
229   begin
230 
231    if x=0 then exit;
232 
233    bi[x]:=max(bi[lc[x]],bi[rc[x]],a[x])+o[x];
234 
235    toroot(f[x]);
236 
237   end;
238 
239  
240 
241  procedure findk(s,x:longint);inline; //寻找
242 
243   begin
244 
245     tonext(x);
246 
247     if q[lc[x]]+1=s then qu:=x;
248 
249     if q[lc[x]]+1<s then findk(s-q[lc[x]]-1,rc[x]);
250 
251     if q[lc[x]]+1>s then findk(s,lc[x]);
252 
253   end;
254 
255  
256 
257  procedure init; inline;
258 
259  var i,j,k:longint;
260 
261   begin
262 
263     readln(n,m);
264 
265     a[1]:=-maxlongint;a[n+2]:=-maxlongint;a[0]:=-maxlongint;bi[0]:=-maxlongint;
266 
267 //在序列左边插入一个节点,右边也插入一个节点,作为边界。注意0节点的初始化。
268 
269     built(1,n+2);root:=(1+n+2)div 2;
270 
271     fillchar(c,sizeof(c),false);
272 
273     for i:=1 to m do
274 
275      begin
276 
277       read(k,lx,rx);
278 
279       inc(lx);inc(rx);
280 
281       findk(lx-1,root);lx:=qu; //寻找询问区间左边界,边界即为询问区间最左边的节点-1
282 
283       findk(rx+1,root);rx:=qu;//寻找询问区间右边界,..........最右边的节点+1
284 
285       splay(lx,0);root:=lx; //将lx旋转到根节点,rx旋转到根节点的右孩子节点,这样rx的左孩子即为询问区间。
286 
287       splay(rx,root);
288 
289       case k of //3种操作
290 
291        1:begin
292 
293            read(v);
294 
295            inc(o[lc[rx]],v); //修改状态
296 
297            inc(bi[lc[rx]],v);
298 
299            toroot(rx); //更新父亲节点的最大值记录
300 
301          end;
302 
303        2:begin
304 
305            c[lc[rx]]:=not(c[lc[rx]]); //翻转,改变翻转记录
306 
307          end;
308 
309        3:begin
310 
311            writeln(bi[lc[rx]]);
312 
313          end;
314 
315       end;
316 
317      end;
318 
319   end;
320 
321 Begin
322 
323  assign(input,'input.in');reset(input);
324 
325  assign(output,'output1.out');rewrite(Output);
326 
327    init;
328 
329  close(output);
330 
331 end.

 

posted on 2016-03-02 20:06  Yesphet  阅读(199)  评论(0编辑  收藏  举报