综合各位大大博客后整理的模板:
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 }