这两题都是link cut tree的裸题
之前看Qtree的论文,只会在确定父子关系的情况下连边和删边
如果在任意两个点连边删边怎么做呢?
这时候我们不能随意的将一个点的父节点设为另一个点,因为其中某个点的父节点可能已经被设为另外某点了
其实很简单,连边的时候,我们只要把x变成其所在原树的根,这样x是没有父节点了
然后把x的父节点设为y即可,删边、询问路径的道理类似,具体见程序
给出的是bzoj2631的程序

  1 const mo=51061;
  2 
  3 var fa,q,a,mul,add,size,sum:array[0..100010] of longint;
  4     rev:array[0..100010] of boolean;
  5     son:array[0..100010,1..2] of longint;
  6     i,x0,y0,x,y,z,n,m,t:longint;
  7     ch:char;
  8 
  9 function root(x:longint):boolean;  //判断是Auxiliary tree(splay)上的父节点还是path parent
 10   begin
 11     exit((son[fa[x],1]<>x) and (son[fa[x],2]<>x));
 12   end;
 13 
 14 procedure swap(var a,b:longint);
 15   var c:longint;
 16   begin
 17     c:=a;
 18     a:=b;
 19     b:=c;
 20   end;
 21 
 22 procedure update(x:longint);
 23   var l,r:longint;
 24   begin
 25     l:=son[x,1];
 26     r:=son[x,2];
 27     size[x]:=(size[l]+size[r]+1) mod mo;
 28     sum[x]:=(a[x]+sum[l]+sum[r]) mod mo;
 29   end;
 30 
 31 procedure calc(x,c,j:longint);
 32   begin
 33     if (c<=42000) then  //常数优化,少用int64
 34     begin
 35       mul[x]:=mul[x]*c mod mo;
 36       add[x]:=(add[x]*c+j) mod mo;
 37       sum[x]:=(sum[x]*c+int64(j)*int64(size[x])) mod mo;
 38       a[x]:=(a[x]*c+j) mod mo;
 39     end
 40     else begin
 41       mul[x]:=int64(mul[x])*int64(c) mod mo;
 42       add[x]:=(int64(add[x])*int64(c)+j) mod mo;
 43       sum[x]:=(int64(sum[x])*int64(c)+int64(j)*int64(size[x])) mod mo;
 44       a[x]:=(int64(a[x])*int64(c)+j) mod mo;
 45     end;
 46   end;
 47 
 48 
 49 procedure push(x:longint);
 50   begin
 51     if rev[x] then
 52     begin
 53       rev[son[x,1]]:=not rev[son[x,1]];
 54       rev[son[x,2]]:=not rev[son[x,2]];
 55       swap(son[x,1],son[x,2]);
 56       rev[x]:=false;
 57     end;
 58     if (mul[x]<>1) or (add[x]<>0) then
 59     begin
 60       if son[x,1]<>0 then calc(son[x,1],mul[x],add[x]);
 61       if son[x,2]<>0 then calc(son[x,2],mul[x],add[x]);
 62       mul[x]:=1;
 63       add[x]:=0;
 64     end;
 65   end;
 66 
 67 procedure rotate(x,w:longint);
 68   var y:longint;
 69   begin
 70     y:=fa[x];
 71     if not root(y) then
 72     begin
 73       if son[fa[y],1]=y then son[fa[y],1]:=x
 74       else son[fa[y],2]:=x;
 75     end;
 76     fa[x]:=fa[y];
 77     son[y,3-w]:=son[x,w];
 78     if son[x,w]<>0 then fa[son[x,w]]:=y;
 79     son[x,w]:=y;
 80     fa[y]:=x;
 81     update(y);
 82   end;
 83 
 84 procedure splay(x:longint);
 85   var y,t,i:longint;
 86       ff:boolean;
 87   begin
 88     t:=0;
 89     i:=x;
 90     while not root(i) do
 91     begin
 92       inc(t);
 93       q[t]:=i;
 94       i:=fa[i];
 95     end;
 96     inc(t);
 97     q[t]:=i;
 98     for i:=t downto 1 do
 99       push(q[i]);
100     ff:=true;
101     if t=1 then exit; 
102     while ff do
103     begin
104       y:=fa[x];
105       if y=q[t] then
106       begin
107         if son[y,1]=x then rotate(x,2)
108         else rotate(x,1);
109         ff:=false;
110       end
111       else begin
112         if fa[y]=q[t] then ff:=false;
113         if son[fa[y],1]=y then
114         begin
115           if son[y,1]=x then rotate(y,2)
116           else rotate(x,1);
117           rotate(x,2);
118         end
119         else begin
120           if son[y,1]=x then rotate(x,2)
121           else rotate(y,1);
122           rotate(x,1);
123         end;
124       end;
125     end;
126     update(x);
127   end;
128 
129 procedure access(x:longint);
130   var y:longint;
131   begin
132     y:=0;
133     repeat
134       splay(x);
135       son[x,2]:=y;
136       update(x);  //这里要记得维护
137       y:=x;
138       x:=fa[x];
139     until x=0;
140   end;
141 
142 procedure makeroot(x:longint);
143   begin
144     access(x);  //执行access之后,x和当前树的根之间的路径构成Auxiliary tree
145     splay(x);   //将x旋到Auxiliary tree的根,这时候x没有右孩子,左子树的点都是x的祖辈
146     rev[x]:=not rev[x];  //执行翻转操作,这时候x是Auxiliary tree上最小的点,也就变成了原树的根
147   end;
148 
149 procedure link(x,y:longint);
150   begin
151     makeroot(x);
152     fa[x]:=y;
153   end;
154 
155 procedure cut(x,y:longint); 
156   begin
157     makeroot(x);
158     access(y);
159     splay(y);
160     son[y,1]:=0;
161     fa[x]:=0;
162   end;
163 
164 procedure path(x,y:longint); //构成x到y的路径
165   begin
166     makeroot(x);
167     access(y); //x到y路径上的点就在一棵Auxiliary tree中
168     splay(y);  
169   end;
170 
171 begin
172   readln(n,m);
173   for i:=1 to n do
174   begin
175     a[i]:=1;
176     size[i]:=1;
177     sum[i]:=1;
178     mul[i]:=1;
179   end;
180   for i:=1 to n-1 do
181   begin
182     readln(x,y);
183     link(x,y);
184   end;
185   for i:=1 to m do
186   begin
187     read(ch);
188     if ch='+' then
189     begin
190       readln(x,y,z);
191       z:=z mod mo;
192       path(x,y);
193       calc(y,1,z);
194     end
195     else if ch='-' then
196     begin
197       readln(x0,y0,x,y);
198       cut(x0,y0);
199       link(x,y);
200     end
201     else if ch='*' then
202     begin
203       readln(x,y,z);
204       z:=z mod mo;
205       path(x,y);
206       calc(y,z,0);
207     end
208     else begin
209       readln(x,y);
210       path(x,y);
211       writeln(sum[y]);
212     end;
213   end;
214 end.
View Code

 

posted on 2015-02-15 22:45  acphile  阅读(149)  评论(0编辑  收藏  举报