好题,先离线把连通块变成连续的区间
每次连通块合并就相当于两个区间合并
这样就轻易的用线段树解决了

 

  1 type node=record
  2        wh:string[2];
  3        x,y:longint;
  4      end;
  5 
  6 var lazy,tree:array[0..300010*4] of longint;
  7     q:array[0..300010] of node;
  8     a,b,c,last,next,fa:array[0..300010] of longint;
  9     i,n,m,x,y,t:longint;
 10     ch:char;
 11 
 12 procedure swap(var a,b:longint);
 13   var c:longint;
 14   begin
 15     c:=a;
 16     a:=b;
 17     b:=c;
 18   end;
 19 
 20 function max(a,b:longint):longint;
 21   begin
 22     if a>b then exit(a) else exit(b);
 23   end;
 24 
 25 function getf(x:longint):longint;
 26   begin
 27     if fa[x]<>x then fa[x]:=getf(fa[x]);
 28     exit(fa[x]);
 29   end;
 30 
 31 procedure push(i:longint);
 32   begin
 33     inc(lazy[i*2],lazy[i]);
 34     inc(tree[i*2],lazy[i]);
 35     inc(lazy[i*2+1],lazy[i]);
 36     inc(tree[i*2+1],lazy[i]);
 37     lazy[i]:=0;
 38   end;
 39 
 40 function ask(i,l,r,x,y:longint):longint;
 41   var m,s:longint;
 42   begin
 43     if (x<=l) and (y>=r) then exit(tree[i])
 44     else begin
 45       if lazy[i]<>0 then push(i);
 46       m:=(l+r) shr 1;
 47       s:=-2147483647;
 48       if x<=m then s:=ask(i*2,l,m,x,y);
 49       if y>m then s:=max(s,ask(i*2+1,m+1,r,x,y));
 50       exit(s);
 51     end;
 52   end;
 53 
 54 procedure add(i,l,r,x,y,z:longint);
 55   var m:longint;
 56   begin
 57     if (x<=l) and (y>=r) then
 58     begin
 59       inc(tree[i],z);
 60       inc(lazy[i],z);
 61     end
 62     else begin
 63       if lazy[i]<>0 then push(i);
 64       m:=(l+r) shr 1;
 65       if x<=m then add(i*2,l,m,x,y,z);
 66       if y>m then add(i*2+1,m+1,r,x,y,z);
 67       tree[i]:=max(tree[i*2],tree[i*2+1]);
 68     end;
 69   end;
 70 
 71 procedure build(i,l,r:longint);
 72   var m:longint;
 73   begin
 74     if l=r then tree[i]:=a[c[l]]
 75     else begin
 76       m:=(l+r) shr 1;
 77       build(i*2,l,m);
 78       build(i*2+1,m+1,r);
 79       tree[i]:=max(tree[i*2],tree[i*2+1]);
 80     end;
 81   end;
 82 
 83 begin
 84   readln(n);
 85   for i:=1 to n do
 86   begin
 87     read(a[i]);
 88     fa[i]:=i;
 89     last[i]:=i;
 90   end;
 91   readln(m);
 92   for i:=1 to m do
 93   begin
 94     read(ch);
 95     q[i].wh:=ch;
 96     read(ch);
 97     q[i].wh:=q[i].wh+ch;
 98     if q[i].wh='U ' then
 99     begin
100       readln(q[i].x,q[i].y);
101       x:=getf(q[i].x);
102       y:=getf(q[i].y);
103       if x=y then continue;
104       fa[y]:=x;
105       next[last[x]]:=y;
106       last[x]:=last[y];
107     end
108     else if (q[i].wh='A1') or (q[i].wh='A2') then
109       readln(q[i].x,q[i].y)
110     else if (q[i].wh='F3') then readln
111     else readln(q[i].x);
112   end;
113 
114   for i:=1 to n do
115     if fa[i]=i then
116     begin
117       x:=i;
118       while x<>0 do
119       begin
120         inc(t);
121         b[x]:=t;
122         c[t]:=x;
123         x:=next[x];
124       end;
125     end;
126 
127   build(1,1,n);
128   for i:=1 to n do
129   begin
130     fa[i]:=i;
131     last[i]:=i;
132   end;
133 
134   for i:=1 to m do
135     if q[i].wh='U ' then
136     begin
137       x:=getf(q[i].x);
138       y:=getf(q[i].y);
139       if x=y then continue;
140       fa[y]:=x;
141       last[x]:=last[y];
142     end
143     else if q[i].wh='A1' then
144       add(1,1,n,b[q[i].x],b[q[i].x],q[i].y)
145     else if q[i].wh='A2' then
146     begin
147       x:=getf(q[i].x);
148       y:=last[x];
149       add(1,1,n,b[x],b[y],q[i].y);
150     end
151     else if q[i].wh='A3' then
152     begin
153       inc(tree[1],q[i].x);
154       inc(lazy[1],q[i].x);
155     end
156     else if q[i].wh='F1' then
157       writeln(ask(1,1,n,b[q[i].x],b[q[i].x]))
158     else if q[i].wh='F2' then
159     begin
160       x:=getf(q[i].x);
161       y:=last[x];
162       writeln(ask(1,1,n,b[x],b[y]));
163     end
164     else writeln(tree[1]);
165 end.
View Code

 

posted on 2015-02-07 10:43  acphile  阅读(119)  评论(0编辑  收藏  举报