这两题都是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.