综合各位大大博客后整理的模板:

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 const int maxn = 10000 + 10;
  5 struct LCT
  6 {
  7     struct node
  8     {
  9         int fa, ch[2]; //父亲(Splay对应的链向上由轻边连着哪个节点)、左右儿子
 10         int reverse;//区间反转标记
 11         bool  is_root;   //是否是所在Splay的根
 12         int siz;
 13     }Tree[maxn];
 14     int n;
 15 
 16     void init(int MN)
 17     {
 18         for (int i = 1; i <= MN; i++)
 19         {
 20             Tree[i].reverse = Tree[i].fa = Tree[i].ch[0] = Tree[i].ch[1] = 0;
 21             Tree[i].is_root = true;
 22             Tree[i].siz = 1;
 23 
 24         }
 25     }
 26 
 27     bool getson(int x)
 28     {//x是否为重儿子
 29         return x == Tree[Tree[x].fa].ch[1];
 30     }
 31     bool isroot(int x)
 32     {
 33         return Tree[Tree[x].fa].ch[0] != x && Tree[Tree[x].fa].ch[1] != x;
 34     }
 35     void pushreverse(int x)
 36     {
 37         if (!x)return;
 38         swap(Tree[x].ch[0], Tree[x].ch[1]);
 39         Tree[x].reverse ^= 1;
 40     }
 41     void pushdown(int x)
 42     {//下传反转标记
 43         if (Tree[x].reverse)
 44         {
 45             pushreverse(Tree[x].ch[0]);
 46             pushreverse(Tree[x].ch[1]);
 47             Tree[x].reverse = 0;
 48         }
 49     }
 50 
 51     void update(int x)
 52     {
 53         int l = Tree[x].ch[0], r = Tree[x].ch[1];
 54         Tree[x].siz = 1;
 55         if (l) Tree[x].siz += Tree[l].siz;
 56         if (r) Tree[x].siz += Tree[r].siz;
 57     }
 58 
 59     void rotate(int x)
 60     {//将x旋转为根
 61         if (Tree[x].is_root)return;
 62         int k = getson(x), fa = Tree[x].fa;
 63         int fafa = Tree[fa].fa;
 64         pushdown(fa); pushdown(x);    //先要下传标记
 65         Tree[fa].ch[k] = Tree[x].ch[k ^ 1];
 66         if (Tree[x].ch[k ^ 1])Tree[Tree[x].ch[k ^ 1]].fa = fa;
 67         Tree[x].ch[k ^ 1] = fa;
 68         Tree[fa].fa = x;
 69         Tree[x].fa = fafa;
 70         if (!Tree[fa].is_root)Tree[fafa].ch[fa == Tree[fafa].ch[1]] = x;
 71         else Tree[x].is_root = true, Tree[fa].is_root = false;
 72         update(fa);update(x);    //如果维护了信息,就要更新节点
 73     }
 74     void push(int x)
 75     {
 76         if (!Tree[x].is_root) push(Tree[x].fa);
 77         pushdown(x);
 78     }
 79     int findroot(int x) 
 80     {//找到x在原树中的根节点 
 81         access(x); Splay(x);
 82         pushdown(x);
 83         while (Tree[x].ch[0]) pushdown(x = Tree[x].ch[0]);//找到深度最小的点即为根节点 
 84         return x;
 85     }
 86     void Splay(int x)
 87     {//让x成为Splay的根,且x不含右儿子
 88         push(x);   //在Splay到根之前,必须先传完反转标记
 89         for (int fa; !Tree[x].is_root; rotate(x)) {
 90             if (!Tree[fa = Tree[x].fa].is_root) {
 91                 rotate((getson(x) == getson(fa)) ? fa : x);
 92             }
 93         }
 94     }
 95     void access(int x)
 96     {//访问某节点。作用是:对于访问的节点x,打通一条从树根(真实的LCT树)到x的重链;如果x往下是重链,那么把x往下的重边改成轻边。结束后x没有右儿子(没有深度比他大的点)
 97         int y = 0;
 98         do {
 99             Splay(x);
100             Tree[Tree[x].ch[1]].is_root = true;
101             Tree[Tree[x].ch[1] = y].is_root = false;
102             update(x);    //如果维护了信息记得更新。
103             x = Tree[y = x].fa;
104         } while (x);
105     }
106     void mroot(int x)
107     {//把某个节点变成树根(这里的根指的是整棵LCT的根)
108         access(x);//使x与根结点处在同一棵splay中
109         Splay(x);//x成为这棵splay的根,x只有左儿子
110         //由于根节点所在的splay中,根节点没有左儿子(没有深度比他小的节点),将x的左右子树翻转
111         pushreverse(x);
112     }
113     void link(int u, int v)
114     {//连接u所在的LCT和v所在的LCT
115         mroot(u);//先让u成为其所在LCT的根
116         if(findroot(v)!=u)Tree[u].fa = v;//如果u与v不在同一棵splay中,就把v设置为u的父亲
117     }
118     void cut(int u, int v)
119     {//分离出两棵LCT
120         mroot(u);   //先让u成为其所在LCT的根
121         access(v); //让u和v在同一棵Splay中
122         Splay(v);    //连接u、v,u是v的左儿子
123         pushdown(v);     //先下传标记
124         if (Tree[v].ch[0])
125         {
126             Tree[Tree[v].ch[0]].fa = Tree[v].fa;
127             Tree[Tree[v].ch[0]].is_root = true;
128         }
129         Tree[v].fa = 0; Tree[v].ch[0] = 0;
130         //v的左孩子表示v上方相连的重链
131         update(v);  //记得维护信息
132     }
133 
134     bool judge(int u, int v)
135     {//判断u和v是否连通
136         while (Tree[u].fa) u = Tree[u].fa;
137         while (Tree[v].fa) v = Tree[v].fa;
138         return u == v;
139     }
140     void split(int u, int v)
141     {//获取u->v的路径
142         mroot(u);//让u成为根结点
143         access(v);//访问v
144         Splay(v);//把v转到根结点,此时u的父亲为v
145     }
146     int Query_deep(int x)
147     {//询问x到LCT根的距离(深度)
148         access(x);
149         Splay(x);
150         return Tree[x].siz;
151     }
152 
153     void modify(int x,int v)
154     {//改变点值
155         access(x);
156         Splay(x);
157         //Tree[x].val = v;更改值
158         update(x);
159 
160     }
161 
162 }lct;
163 int main()
164 {
165 
166     return 0;
167 }
View Code

相关文章:

  • 2021-05-19
  • 2021-11-02
  • 2021-06-10
  • 2021-08-03
  • 2022-12-23
  • 2018-08-10
猜你喜欢
  • 2022-12-23
  • 2022-01-10
  • 2021-08-09
  • 2022-12-23
  • 2022-12-23
  • 2021-11-04
  • 2021-09-05
相关资源
相似解决方案