[关闭]
@Junlier 2018-08-19T14:32:29.000000Z 字数 2680 阅读 1901

Link-Cut-Tree学习(LCT)

数据结构——LCT
真不敢想象我居然学会LCT了,但是我仍然不想写一篇博客来梳理
我怕一梳理自己又不懂了
但是作为一名朴实沉毅的cjoier,我决定小小的梳理一下,并不打算很精致......
我这样说也是有资本的,下面推荐两个教会我LCT的博客
FlashHu的LCT总结
xzy的好注释+板子
其实贴上这两个博客也就没我什么事了,所以,溜了溜了
以后我想复习了直接就点开QwQ

code

当然,一贯不要脸的我,明明自己的代码是看的xzy的,还是附上了自己的代码
PS:不得不承认,set是个好东西啊

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<iomanip>
  7. #include<algorithm>
  8. #include<ctime>
  9. #include<queue>
  10. #include<stack>
  11. #include<vector>
  12. #include<set>
  13. #define rg register
  14. #define il inline
  15. #define lst long long
  16. #define ldb long double
  17. #define N 300050
  18. using namespace std;
  19. const int Inf=1e9;
  20. il int read()
  21. {
  22. rg int s=0,m=0;rg char ch=getchar();
  23. while(ch<'0'||ch>'9'){if(ch=='-')m=1;ch=getchar();}
  24. while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
  25. return m?-s:s;
  26. }
  27. int n,m,top;
  28. int st[N];
  29. set<int> link[N];
  30. struct SPLAY{int fa,v,sum,tag,ch[2];}ljl[N];
  31. il void Pushup(rg int x){ljl[x].sum=ljl[ljl[x].ch[0]].sum^ljl[ljl[x].ch[1]].sum^ljl[x].v;}
  32. il void Reverse(rg int x){swap(ljl[x].ch[0],ljl[x].ch[1]);ljl[x].tag^=1;}
  33. il void Pushdown(rg int x)
  34. {
  35. if(ljl[x].tag)
  36. {
  37. if(ljl[x].ch[0])Reverse(ljl[x].ch[0]);
  38. if(ljl[x].ch[1])Reverse(ljl[x].ch[1]);
  39. ljl[x].tag=0;
  40. }
  41. }
  42. il bool Isroot(rg int x){return ((ljl[ljl[x].fa].ch[0]!=x)&&(ljl[ljl[x].fa].ch[1]!=x));}
  43. il void Rotate(rg int x)
  44. {
  45. rg int y=ljl[x].fa,z=ljl[y].fa;
  46. rg int k=ljl[y].ch[1]==x;
  47. if(!Isroot(y))ljl[z].ch[ljl[z].ch[1]==y]=x;
  48. ljl[x].fa=z;
  49. ljl[y].ch[k]=ljl[x].ch[k^1];
  50. ljl[ljl[x].ch[k^1]].fa=y;
  51. ljl[x].ch[k^1]=y;
  52. ljl[y].fa=x;
  53. Pushup(y);
  54. }
  55. il void Splay(rg int x)
  56. {
  57. st[++top]=x;
  58. for(rg int i=x;!Isroot(i);i=ljl[i].fa)st[++top]=ljl[i].fa;
  59. while(top)Pushdown(st[top--]);
  60. while(!Isroot(x))
  61. {
  62. rg int y=ljl[x].fa,z=ljl[y].fa;
  63. if(!Isroot(y))(ljl[y].ch[0]==x)^(ljl[z].ch[0]==y)?Rotate(x):Rotate(y);
  64. Rotate(x);
  65. }
  66. Pushup(x);
  67. }
  68. il void Access(rg int x)
  69. {
  70. for(rg int y=0;x;y=x,x=ljl[x].fa)
  71. Splay(x),ljl[x].ch[1]=y,Pushup(x);
  72. }
  73. il void Make_root(rg int x){Access(x),Splay(x),Reverse(x);}
  74. il int Find_root(rg int x)
  75. {
  76. Access(x),Splay(x);
  77. while(ljl[x].ch[0])x=ljl[x].ch[0];
  78. return x;
  79. }
  80. il void Split(rg int x,rg int y){Make_root(x),Access(y),Splay(y);}
  81. il void Link(rg int x,rg int y)
  82. {
  83. Make_root(x),ljl[x].fa=y;
  84. link[x].insert(y),link[y].insert(x);
  85. }
  86. il void Cut(rg int x,rg int y)
  87. {
  88. Split(x,y);
  89. ljl[x].fa=ljl[y].ch[0]=0;
  90. link[x].erase(y),link[y].erase(x);
  91. }
  92. int main()
  93. {
  94. freopen("s.in","r",stdin);
  95. n=read(),m=read();
  96. for(rg int i=1;i<=n;++i)
  97. ljl[i].sum=ljl[i].v=read();
  98. for(rg int i=1;i<=m;++i)
  99. {
  100. rg int opt=read(),x=read(),y=read();
  101. if(opt==0)//x--y异或和
  102. {
  103. Split(x,y);//抠出路径,此时这条路径的异或和存在SPLAY根节点y中
  104. printf("%d\n",ljl[y].sum);//直接输出sum[y]就ok
  105. }
  106. if(opt==1)//连接x--y
  107. if(Find_root(x)^Find_root(y))Link(x,y);//如果不是同一个联通块里就连边
  108. if(opt==2)//删除x--y
  109. if(link[x].find(y)!=link[x].end())Cut(x,y);//如果x所连的边中找到了y(没有找到set尾部)就删边
  110. if(opt==3)//把x的权值改为y
  111. {
  112. Access(x),Splay(x);//把x抠出来并放到SPLAY的根节点(不会影响到其他元素的sum)
  113. ljl[x].v=y,Pushup(x);//直接修改就行,顺便更新一下自己
  114. }
  115. }
  116. return 0;
  117. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注