Top Tree模板题,写起来真不是一般的蛋疼,调了两天。常数写渣了TAT

Top Tree就是在LCT的基础上加以改动,将虚边也用splay维护,

对于A向儿子所连出去的虚边,用Splay维护↓

为了保证所有虚儿子不存在父子关系,需要让它们都是叶子节点,所以需要引入白色的内部点来维持这个结构。

就能支持子树操作了。

对于这样一棵以1为根的树。

在Top Tree中是这样维护的。

实现起来就是把原来son[2]扩充到son[4]

son[0]和son[1]仍然对应实链splay的两个儿子

son[2]和son[3]对应虚边splay的两个儿子

Add操作:

Add(x,y)操作就是从x点连一条虚边到y,使得x是y的父亲。

这就等价于在x的虚边splay中插入y这个叶子节点,必要的话要新建内部点。

Del操作:

Del(x)操作就是把x点和它父亲之间连着的虚边断开。

这就等价于在x的父亲的虚边splay中删除x这个叶子节点,必要的话要删除某些已经没用的内部点。

Access操作:

Access(x)操作就是把x到根路径上的所有边都变成实边,并把x向它所有儿子的边都变成虚边。

考虑普通Link-Cut Tree的Access过程:

  1. void access(int x){
  2. for(int y=0;x;y=x,x=f[x]){
  3. splay(x);
  4. son[x][1]=y;
  5. up(x);
  6. }
  7. }

每一步都是实边虚边的转化,有了Add和Del操作,可以很自然的改写成:

  1. void access(int x){
  2. for(int y=0;x;y=x,x=fa(x)){
  3. splay(x);
  4. del(y);
  5. add(x,son[x][1]);
  6. setson(x,1,y);
  7. up(x);
  8. }
  9. }

Makeroot操作:

与Link-Cut Tree一致,注意翻转只交换son[0]和son[1]。

Link操作:

考虑普通Link-Cut Tree的Link过程:

  1. void link(int x,int y){
  2. makeroot(x);
  3. f[x]=y;
  4. access(x);
  5. }

可以很自然的改写成:

  1. void link(int x,int y){
  2. makeroot(x);
  3. add(y,x);
  4. access(x);
  5. }

Cut操作:

与Link-Cut Tree一致。

链操作:

与Link-Cut Tree一致。

子树操作:

方便起见首先Access(x),这样x向它的孩子连着的肯定都是虚边,x的子树部分就是x的虚边Splay。

  1. void changetree(int x,tag p){
  2. access(x);
  3. splay(x);
  4. val[x]=atag(val[x],p);
  5. for(int i=2;i<4;i++)if(son[x][i])tagtree(son[x][i],p,1);
  6. up(x);
  7. splay(x);
  8. }
  9. data asktree(int x){
  10. access(x);
  11. splay(x);
  12. data t=data(val[x]);
  13. for(int i=2;i<4;i++)if(son[x][i])t=t+asum[son[x][i]];
  14. return t;
  15. }

信息的和:

对于每个节点x,需要维护一些域:

in:这个点是否是内部点

val:这个点的点权

csum:链上信息和

tsum:子树信息和(不包括链上)

asum:所有信息和

csum[x]=val[x]+csum[son[x][0]]+csum[son[x][1]]

tsum[x]=tsum[son[x][0]]+tsum[son[x][1]]+asum[son[x][2]]+asum[son[x][3]]

asum[x]=csum[x]+tsum[x]

标记:

对于每个节点x,需要维护一些标记:

rev:链翻转标记

ctag:链修改标记

ttag:子树修改标记(不包括链上)

rev和ctag下传方法与Link-Cut Tree一致,

ttag下传方法为:

如果是在实链中的下传,直接下传到ttag,无需修改。

如果是虚边splay中下传到内部点,下传到ttag并修改。

如果是虚边splay中下传到外部点,下传到ttag和ctag并修改。

垃圾回收:

由于add操作会新增大量内部白点,但是内部白点最多同时只有$O(n)$个,所以需要垃圾回收。

效率:

时间复杂度为$O(\log n)$每次操作,但是常数为97,非常大。

  1. #include<cstdio>
  2. #define N 200010
  3. const int inf=~0U>>1;
  4. inline void swap(int&a,int&b){int c=a;a=b;b=c;}
  5. inline int max(int a,int b){return a>b?a:b;}
  6. inline int min(int a,int b){return a<b?a:b;}
  7. inline void read(int&a){
  8. char c;bool f=0;a=0;
  9. while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
  10. if(c!='-')a=c-'0';else f=1;
  11. while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
  12. if(f)a=-a;
  13. }
  14. struct tag{
  15. int a,b;//ax+b
  16. tag(){a=1,b=0;}
  17. tag(int x,int y){a=x,b=y;}
  18. inline bool ex(){return a!=1||b;}
  19. inline tag operator+(const tag&x){return tag(a*x.a,b*x.a+x.b);}
  20. };
  21. inline int atag(int x,tag y){return x*y.a+y.b;}
  22. struct data{
  23. int sum,minv,maxv,size;
  24. data(){sum=size=0,minv=inf,maxv=-inf;}
  25. data(int x){sum=minv=maxv=x,size=1;}
  26. data(int a,int b,int c,int d){sum=a,minv=b,maxv=c,size=d;}
  27. inline data operator+(const data&x){return data(sum+x.sum,min(minv,x.minv),max(maxv,x.maxv),size+x.size);}
  28. };
  29. inline data operator+(const data&a,const tag&b){return a.size?data(a.sum*b.a+a.size*b.b,atag(a.minv,b),atag(a.maxv,b),a.size):a;}
  30. //son:0-1:重链儿子,2-3:AAA树儿子
  31. int f[N],son[N][4],a[N],tot,rt,rub,ru[N];bool rev[N],in[N];
  32. int val[N];
  33. data csum[N],tsum[N],asum[N];
  34. tag ctag[N],ttag[N];
  35. inline bool isroot(int x,int t){
  36. if(t)return !f[x]||!in[f[x]]||!in[x];
  37. return !f[x]||(son[f[x]][0]!=x&&son[f[x]][1]!=x)||in[f[x]]||in[x];
  38. }
  39. inline void rev1(int x){
  40. if(!x)return;
  41. swap(son[x][0],son[x][1]);rev[x]^=1;
  42. }
  43. inline void tagchain(int x,tag p){
  44. if(!x)return;
  45. csum[x]=csum[x]+p;
  46. asum[x]=csum[x]+tsum[x];
  47. val[x]=atag(val[x],p);
  48. ctag[x]=ctag[x]+p;
  49. }
  50. inline void tagtree(int x,tag p,bool t){
  51. if(!x)return;
  52. tsum[x]=tsum[x]+p;
  53. ttag[x]=ttag[x]+p;
  54. if(!in[x]&&t)tagchain(x,p);else asum[x]=csum[x]+tsum[x];
  55. }
  56. inline void pb(int x){
  57. if(!x)return;
  58. if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
  59. if(!in[x]&&ctag[x].ex())tagchain(son[x][0],ctag[x]),tagchain(son[x][1],ctag[x]),ctag[x]=tag();
  60. if(ttag[x].ex()){
  61. tagtree(son[x][0],ttag[x],0),tagtree(son[x][1],ttag[x],0);
  62. tagtree(son[x][2],ttag[x],1),tagtree(son[x][3],ttag[x],1);
  63. ttag[x]=tag();
  64. }
  65. }
  66. inline void up(int x){
  67. tsum[x]=data();
  68. for(int i=0;i<2;i++)if(son[x][i])tsum[x]=tsum[x]+tsum[son[x][i]];
  69. for(int i=2;i<4;i++)if(son[x][i])tsum[x]=tsum[x]+asum[son[x][i]];
  70. if(in[x]){
  71. csum[x]=data();
  72. asum[x]=tsum[x];
  73. }else{
  74. csum[x]=data(val[x]);
  75. for(int i=0;i<2;i++)if(son[x][i])csum[x]=csum[x]+csum[son[x][i]];
  76. asum[x]=csum[x]+tsum[x];
  77. }
  78. }
  79. inline int child(int x,int t){pb(son[x][t]);return son[x][t];}
  80. inline void rotate(int x,int t){
  81. int y=f[x],w=(son[y][t+1]==x)+t;
  82. son[y][w]=son[x][w^1];
  83. if(son[x][w^1])f[son[x][w^1]]=y;
  84. if(f[y])for(int z=f[y],i=0;i<4;i++)if(son[z][i]==y)son[z][i]=x;
  85. f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
  86. }
  87. inline void splay(int x,int t=0){
  88. int s=1,i=x,y;a[1]=i;
  89. while(!isroot(i,t))a[++s]=i=f[i];
  90. while(s)pb(a[s--]);
  91. while(!isroot(x,t)){
  92. y=f[x];
  93. if(!isroot(y,t)){if((son[f[y]][t]==y)^(son[y][t]==x))rotate(x,t);else rotate(y,t);}
  94. rotate(x,t);
  95. }
  96. up(x);
  97. }
  98. inline int newnode(){
  99. int x=rub?ru[rub--]:++tot;
  100. son[x][2]=son[x][3]=0;in[x]=1;
  101. return x;
  102. }
  103. inline void setson(int x,int t,int y){son[x][t]=y;f[y]=x;}
  104. inline int pos(int x){for(int i=0;i<4;i++)if(son[f[x]][i]==x)return i;return 4;}
  105. inline void add(int x,int y){//从x连出一条虚边到y
  106. if(!y)return;
  107. pb(x);
  108. for(int i=2;i<4;i++)if(!son[x][i]){
  109. setson(x,i,y);
  110. return;
  111. }
  112. while(son[x][2]&&in[son[x][2]])x=child(x,2);
  113. int z=newnode();
  114. setson(z,2,son[x][2]);
  115. setson(z,3,y);
  116. setson(x,2,z);
  117. splay(z,2);
  118. }
  119. inline void del(int x){//将x与其虚边上的父亲断开
  120. if(!x)return;
  121. splay(x);
  122. if(!f[x])return;
  123. int y=f[x];
  124. if(in[y]){
  125. int s=1,i=y,z=f[y];a[1]=i;
  126. while(!isroot(i,2))a[++s]=i=f[i];
  127. while(s)pb(a[s--]);
  128. if(z){
  129. setson(z,pos(y),child(y,pos(x)^1));
  130. splay(z,2);
  131. }
  132. ru[++rub]=y;
  133. }else{
  134. son[y][pos(x)]=0;
  135. splay(y);
  136. }
  137. f[x]=0;
  138. }
  139. inline int fa(int x){//x通过虚边的父亲
  140. splay(x);
  141. if(!f[x])return 0;
  142. if(!in[f[x]])return f[x];
  143. int t=f[x];
  144. splay(t,2);
  145. return f[t];
  146. }
  147. inline int access(int x){
  148. int y=0;
  149. for(;x;y=x,x=fa(x)){
  150. splay(x);
  151. del(y);
  152. add(x,son[x][1]);
  153. setson(x,1,y);
  154. up(x);
  155. }
  156. return y;
  157. }
  158. inline int lca(int x,int y){
  159. access(x);
  160. return access(y);
  161. }
  162. inline int root(int x){
  163. access(x);
  164. splay(x);
  165. while(son[x][0])x=son[x][0];
  166. return x;
  167. }
  168. inline void makeroot(int x){
  169. access(x);
  170. splay(x);
  171. rev1(x);
  172. }
  173. inline void link(int x,int y){
  174. makeroot(x);
  175. add(y,x);
  176. access(x);
  177. }
  178. inline void cut(int x){
  179. access(x);
  180. splay(x);
  181. f[son[x][0]]=0;
  182. son[x][0]=0;
  183. up(x);
  184. }
  185. inline void changechain(int x,int y,tag p){
  186. makeroot(x);
  187. access(y);
  188. splay(y);
  189. tagchain(y,p);
  190. }
  191. inline data askchain(int x,int y){
  192. makeroot(x);
  193. access(y);
  194. splay(y);
  195. return csum[y];
  196. }
  197. inline void changetree(int x,tag p){
  198. access(x);
  199. splay(x);
  200. val[x]=atag(val[x],p);
  201. for(int i=2;i<4;i++)if(son[x][i])tagtree(son[x][i],p,1);
  202. up(x);
  203. splay(x);
  204. }
  205. inline data asktree(int x){
  206. access(x);
  207. splay(x);
  208. data t=data(val[x]);
  209. for(int i=2;i<4;i++)if(son[x][i])t=t+asum[son[x][i]];
  210. return t;
  211. }
  212. int n,m,x,y,z,k,i,ed[N][2];
  213. int main(){
  214. read(n);read(m);
  215. tot=n;
  216. for(i=1;i<n;i++)read(ed[i][0]),read(ed[i][1]);
  217. for(i=1;i<=n;i++)read(val[i]),up(i);
  218. for(i=1;i<n;i++)link(ed[i][0],ed[i][1]);
  219. read(rt);
  220. makeroot(rt);
  221. while(m--){
  222. read(k);
  223. if(k==1){//换根
  224. read(rt);
  225. makeroot(rt);
  226. }
  227. if(k==9){//x的父亲变成y
  228. read(x),read(y);
  229. if(lca(x,y)==x)continue;
  230. cut(x);
  231. link(y,x);
  232. makeroot(rt);
  233. }
  234. if(k==0){//子树赋值
  235. read(x),read(y);
  236. changetree(x,tag(0,y));
  237. }
  238. if(k==5){//子树加
  239. read(x),read(y);
  240. changetree(x,tag(1,y));
  241. }
  242. if(k==3){//子树最小值
  243. read(x);
  244. printf("%d\n",asktree(x).minv);
  245. }
  246. if(k==4){//子树最大值
  247. read(x);
  248. printf("%d\n",asktree(x).maxv);
  249. }
  250. if(k==11){//子树和
  251. read(x);
  252. printf("%d\n",asktree(x).sum);
  253. }
  254. if(k==2){//链赋值
  255. read(x),read(y),read(z);
  256. changechain(x,y,tag(0,z));
  257. makeroot(rt);
  258. }
  259. if(k==6){//链加
  260. read(x),read(y),read(z);
  261. changechain(x,y,tag(1,z));
  262. makeroot(rt);
  263. }
  264. if(k==7){//链最小值
  265. read(x),read(y);
  266. printf("%d\n",askchain(x,y).minv);
  267. makeroot(rt);
  268. }
  269. if(k==8){//链最大值
  270. read(x),read(y);
  271. printf("%d\n",askchain(x,y).maxv);
  272. makeroot(rt);
  273. }
  274. if(k==10){//链和
  275. read(x),read(y);
  276. printf("%d\n",askchain(x,y).sum);
  277. makeroot(rt);
  278. }
  279. }
  280. return 0;
  281. }

  

BZOJ3153 : Sone1的更多相关文章

  1. bzoj 3153: Sone1 Toptree

    3153: Sone1 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 511  Solved: 202[Submit][Status][Discuss ...

  2. BZOJ 3153 Sone1

    题解:水水哒AAA树啦 #include<iostream> #include<cstdio> #include<cmath> #include<algori ...

  3. sone1动态树

    这尼吗桑心病狂的动态树:http://www.lydsy.com/JudgeOnline/problem.php?id=3153 终于让哥以一种碉堡的姿势过了: 牛B轰轰的最后两个都是我的...无法超 ...

  4. 【BZOJ】【3210】花神的浇花集会

    曼哈顿距离与切比雪夫距离 QAQ蒟蒻并不知道切比雪夫距离是什么……并不会做这道题…… 去膜拜了PoPoQQQ大爷的题解: 题目大意:给定平面上的n个点,求一个点到这n个点的切比雪夫距离之和最小 与31 ...

  5. BZOJ3210: 花神的浇花集会

    3210: 花神的浇花集会 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 238  Solved: 119[Submit][Status] Descri ...

  6. BZOJ_3210_花神的浇花集会_切比雪夫距离

    BZOJ_3210_花神的浇花集会_切比雪夫距离 Description 在花老师的指导下,每周4都有一个集会活动,俗称“浇水”活动. 具体浇水活动详情请见BZOJ3153 但这不是重点 花神出了好多 ...

  7. BZOJ 3210: 花神的浇花集会

    3210: 花神的浇花集会 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 577  Solved: 299[Submit][Status][Discus ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. 【bzoj3210】花神的浇花集会 旋转坐标系

    题目描述 在花老师的指导下,每周4都有一个集会活动,俗称“浇水”活动. 具体浇水活动详情请见BZOJ3153 但这不是重点 花神出了好多题,每道题都有两个参考系数:代码难度和算法难度 花神为了准备浇花 ...

随机推荐

  1. NGUI 粒子显示在上级

    http://bbs.taikr.com/thread-2272-1-1.html [NGUI]3.0+版本,粒子在UI后面显示 -- : 48人阅读 评论() 收藏 举报 [Unity3D][NGU ...

  2. nginx reload

    iwangzheng.com Usage: nginx [-?hvVt] [-s signal] [-c filename] [-p prefix] [-g directives] Options:- ...

  3. BNUOJ 1037 精神控制

    XsuagrX喜欢到处唬人,各种唬.这不,经过刻苦修炼,他终于掌握了Bane Element的Ultra绝技加强版,恶魔掌控(快捷键F)(YY中&……).当XsugarX对某个人胡言乱语Q@# ...

  4. HDOJ 1590

    #include<stdio.h> #include<iostream> #include<stdlib.h> #include<string.h> u ...

  5. OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能

    http://www.hopesoft.org/blog/?p=1188 http://www.imagemagick.org/download/ 2.用法 原始图片是input.jpg,尺寸:160 ...

  6. C++ virtual descructor

    [代码1]  C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546 ...

  7. Windbg程序调试--转载

    WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件. WinDbg是微软很重要的诊断调试工具: 可以查 ...

  8. iOS 利用Context裁剪图片

    下面的代码可以裁剪出圆形的图片, 1,先把不规则图片转成正方形图片 UIGraphicsBeginImageContext(newSize); [image drawInRect:CGRectMake ...

  9. -fomit-frame-pointer 编译选项在gcc 4.8.2版本中的汇编代码研究

    #include void fun(void) { printf("fun"); } int main(int argc, char *argv[]){ fun(); return ...

  10. Java for LeetCode 164 Maximum Gap

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...