lct是一种动态树,用来维护一些动态加边删边的操作的东西.他主要用到几个操作,其实这个算法和树链刨分有点像,但是不能用线段树简单维护,所以我们要用多棵平衡树来维护树上的一个个子树,然后就进行一些很秀的操作.详情见这个博客:FlashHu
这个博客讲的是真的好,特别适合新手看,而且特别细节,(特别带劲).现在我就可以上代码:
模板:
#include <iostream> #include <cassert> #include <cstdio> #include <cmath> #include <ctime> #include <queue> #include <algorithm> #include <cstring> using namespace std; #define duke(i, a, n) for (register int i = a; i <= n; i++) #define lv(i, a, n) for (register int i = a; i >= n; i--) #define clean(a) memset(a, 0, sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while (c = getchar(), c < '0' || c > '9') if (c == '-') op = 1; x = c - '0'; while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if (op) x = -x; } template <class T> void write(T x) { if (x < 0) putchar('-'), x = -x; if (x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 300009; struct node { int fa, ch[2], rev, v, s; } a[N]; int st[N]; #define O(a) cout << #a << " " << a << endl; int n, m; bool isroot(int x) { return !(a[a[x].fa].ch[0] == x || a[a[x].fa].ch[1] == x); } void pushr(int x) { swap(a[x].ch[0], a[x].ch[1]); a[x].rev ^= 1; } void push_down(int k) { if (a[k].rev) { if (a[k].ch[0]) pushr(a[k].ch[0]); if (a[k].ch[1]) pushr(a[k].ch[1]); a[k].rev ^= 1; } } void push_up(int x) { a[x].s = a[a[x].ch[0]].s ^ a[a[x].ch[1]].s ^ a[x].v; } void connect(int x, int fa, int son) { a[x].fa = fa; a[fa].ch[son] = x; } int iden(int x) { return a[a[x].fa].ch[0] == x ? 0 : 1; } void rotate(int x) { int y = a[x].fa; int mroot = a[y].fa; int mrootson = iden(y); int yson = iden(x); int b = a[x].ch[yson ^ 1]; if (!isroot(y)) { a[mroot].ch[mrootson] = x; } a[x].fa = mroot; connect(b, y, yson); connect(y, x, yson ^ 1); push_up(y); push_up(x); } void splay(int x) { int top = 0;int i; st[++top] = x; for (i = x; !isroot(i); i = a[i].fa) { st[++top] = a[i].fa; } for (int i = top; i >= 1; i--) { push_down(st[i]); } while (!isroot(x)) { int y = a[x].fa; if (isroot(y)) { rotate(x); } else if (iden(x) == iden(y)) { rotate(y); rotate(x); } else { rotate(x); rotate(x); } } push_up(x); } void access(int x) { int t = 0; while (x) { splay(x); a[x].ch[1] = t; push_up(x); t = x; x = a[x].fa; } } void make_root(int x) { access(x); splay(x); // a[a[x].ch[0]].rev ^= 1; // a[a[x].ch[1]].rev ^= 1; pushr(x); // swap(a[x].ch[0],a[x].ch[1]); // push_down(x); } void split(int x, int y) { // if (x <= n && y <= n) { make_root(x); access(y); splay(y); // } } int findroot(int x) { access(x); splay(x); push_down(x); while (a[x].ch[0]){ push_down(a[x].ch[0]); x = a[x].ch[0]; } return x; } void link(int x, int y) { make_root(x); int t = findroot(y); assert(t); if ( t != x) a[x].fa = y; } void cut(int x, int y) { make_root(x); int t = findroot(y); assert(t); if (t == x && a[x].fa == y && !a[x].ch[1]) { a[x].fa = a[y].ch[0] = 0; push_up(y); } } int main() { // freopen("in.in","r",stdin); int x, y, typ; read(n); read(m); duke(i, 1, n) { read(a[i].v); push_up(i); } int oup = 0; duke(mi,1,m){ read(typ); read(x); read(y); if (typ == 0) { split(x, y); printf("%d ", a[y].s); ++oup; } else if (typ == 1) { link(x, y); } else if (typ == 2) { cut(x, y); } else { splay(x); a[x].v = y; } // cout<<a[1].ch[0]<<" "<<a[1].ch[1]<<" "<<a[1].fa<<" "<<a[1].v<<" "<<a[1].s<<endl; } return 0; }
魔法森林:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } #define min2(x,y) if(x>y)x=y; const int N = 2e5 + 5; const int P = 131072; struct node { int fa,ch[2],rev,v,mx; }a[N]; int st[N],n,m; struct edge { int u,v,a,b; bool operator < (const edge &oth) const { return a < oth.a; } void getin() { read(u);read(v); read(a);read(b); u |= P;v |= P; } }e[2 * N]; bool isroot(int x) { return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x; } void pushr(int x) { swap(a[x].ch[0],a[x].ch[1]); a[x].rev ^= 1; } void push_down(int x) { if(a[x].rev) { // if(a[a[x].ch[0]].rev) pushr(a[x].ch[0]); // if(a[a[x].ch[1]].rev) pushr(a[x].ch[1]); swap(a[x].ch[0],a[x].ch[1]); a[a[x].ch[0]].rev ^= 1; a[a[x].ch[1]].rev ^= 1; a[x].rev ^= 1; } } void push_up(int x) { a[x].mx = x; if(e[a[x].mx].b < e[a[a[x].ch[0]].mx].b) a[x].mx = a[a[x].ch[0]].mx; if(e[a[x].mx].b < e[a[a[x].ch[1]].mx].b) a[x].mx = a[a[x].ch[1]].mx; } int iden(int x) { return a[a[x].fa].ch[0] == x ? 0 : 1; } void connect(int x,int fa,int son) { a[x].fa = fa; a[fa].ch[son] = x; } void rotate(int x) { int y = a[x].fa; int mroot = a[y].fa; int mrootson = iden(y); int yson = iden(x); int b = a[x].ch[yson ^ 1]; if(!isroot(y)) { a[mroot].ch[mrootson] = x; } a[x].fa = mroot; connect(y,x,yson ^ 1); connect(b,y,yson); push_up(y); // update(x); } void splay(int x) { int top = 0,i; st[++top] = x; for(i = x;!isroot(i);i = a[i].fa) { st[++top] = a[i].fa; } push_down(a[i].fa); for(int i = top;i;i--) { push_down(st[i]); } while(!isroot(x)) { int y = a[x].fa; if(isroot(y)) rotate(x); else if(iden(x) == iden(y)) { rotate(y);rotate(x); } else { rotate(x);rotate(x); } } push_up(x); } void access(int x) { int t = 0; while(x) { splay(x); a[x].ch[1] = t; push_up(x); t = x; x = a[x].fa; } } void makeroot(int x) { access(x); splay(x); a[x].rev ^= 1; } int findroot(int x) { access(x); splay(x); while(a[x].ch[0]) x = a[x].ch[0]; return x; } void link(int x) { int y = e[x].u,z = e[x].v; makeroot(z); a[a[z].fa = x].fa = y; // a[x].fa = y; } void cut(int x) { access(e[x].v); splay(x); a[x].ch[0] = a[x].ch[1] = a[a[x].ch[0]].fa = a[a[x].ch[1]].fa = 0; push_up(x); } int main() { // freopen("2387.in","r",stdin); int ans = INF; read(n);read(m); duke(i,1,m) { e[i].getin(); } sort(e + 1,e + m + 1); int y,z; duke(i,1,m) { if((y = e[i].u) == (z = e[i].v)) continue; makeroot(y); if(y != findroot(z)) link(i); else if(e[i].b < e[a[z].mx].b) { cut(a[z].mx); link(i); } makeroot(1 | P); if((1 | P) == findroot(n | P)) ans = min(ans,e[i].a + e[a[n | P].mx].b); } printf("%d ",ans == INF ? -1 : ans); return 0; }
弹飞绵羊:
#include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<algorithm> #include<vector> #include<complex> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) #define mp make_pair #define cp complex<db> #define enter puts("") const long long INF = 1LL << 60; const double eps = 1e-8; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int ch[2],siz,fa; }a[1000005]; int n,m; int iden(int x) { return a[a[x].fa].ch[0] == x ? 0 : 1; } void connect(int x,int fa,int son) { a[x].fa = fa; a[fa].ch[son] = x; } bool isroot(int x) { return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x; } void push_up(int x) { a[x].siz = a[a[x].ch[0]].siz + a[a[x].ch[1]].siz + 1; } /*void pushr(int x) { swap(a[x].ch[0],a[x].ch[1]); a[x].rev ^= 1; } void push_down(int x) { if(a[x].rev) { if(a[x].ch[0]) pushr(a[x].ch[0]); if(a[x].ch[1]) pushr(a[x].ch[1]); a[x].rev ^= 1; } }*/ void rotate(int x) { int y = a[x].fa; int mroot = a[y].fa; int mrootson = iden(y); int yson =iden(x); int b = a[x].ch[yson ^ 1]; if(!isroot(y)) { a[mroot].ch[mrootson] = x; } a[x].fa = mroot; connect(b,y,yson); connect(y,x,yson ^ 1); push_up(y); } /*inline bool isroot(int x){ return a[a[x].fa].ch[0]==x||a[a[x].fa].ch[1]==x; } void rotate(int x){ int y=a[x].fa,z=a[y].fa,k=a[y].ch[1]==x,w=a[x].ch[!k]; if(isroot(y))a[z].ch[a[z].ch[1]==y] = x;a[x].ch[!k]=y;a[y].ch[k]=w; if(w)a[w].fa=y;a[y].fa=x;a[x].fa=z; push_up(y); }*/ void splay(int x) { while(!isroot(x)) { int y = a[x].fa; if(isroot(y)) rotate(x); else if(iden(x) == iden(y)) { rotate(y);rotate(x); } else { rotate(x);rotate(x); } } push_up(x); } /*void splay(int x){ int y,z; while(isroot(x)){ y=a[x].fa;z=a[y].fa; cout<<x<<endl; if(isroot(y)) rotate((a[y].ch[0]==x)^(a[z].ch[0]==y)?y:x); rotate(x); } push_up(x); }*/ void access(int x) { int t = 0; while(x) { splay(x); a[x].ch[1] = t; t = x; push_up(x); x = a[x].fa; } } int ch,j,k; int main() { // freopen("3203.in","r",stdin); read(n); duke(i,1,n) { a[i].siz = 1; read(k); if(i + k <= n) a[i].fa = i + k; } read(m); while(m--) { read(ch); if(ch == 1) { read(j);j++; access(j);splay(j); printf("%d ",a[j].siz); } else { read(j);read(k); ++j; access(j);splay(j); a[j].ch[0] = a[a[j].ch[0]].fa = 0; if(j + k <= n) a[j].fa = j + k; push_up(j); } } return 0; } /*int main() { freopen("3203.in","r",stdin); register char ch; int n,m,j,k; read(n); for(j=1;j<=n;++j){ a[j].siz=1; read(k); if(j+k<=n)a[j].fa=j+k;//如果弹飞了就不连边 } read(m); int op = 0; while(m--){ read(op); if(op&1){ read(j);++j; access(j);splay(j);//直接查询 printf("%d ",a[j].siz); } else{ read(j);read(k);++j; access(j);splay(j); a[j].ch[0]=a[a[j].ch[0]].fa=0;//直接断边 if(j+k<=n)a[j].fa=j+k;//直接连边 push_ up(j); } } return 0; }*/
洞穴勘测:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int fa,ch[2],rev; }a[10005]; int n,m,st[10005]; bool isroot(int x) { return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x; } void push_down(int k) { if(a[k].rev) { int l = a[k].ch[0]; int r = a[k].ch[1]; a[k].rev ^= 1; a[l].rev ^= 1; a[r].rev ^= 1; swap(a[k].ch[0],a[k].ch[1]); } } int iden(int x) { return a[a[x].fa].ch[0] == x ? 0 : 1; } void connect(int x,int f,int son) { a[x].fa = f; a[f].ch[son] = x; } void rotate(int x) { int y = a[x].fa; int mroot = a[y].fa; int mrootson = iden(y); int yson = iden(x); int b = a[x].ch[yson ^ 1]; if(!isroot(y)) { a[mroot].ch[mrootson] = x; } a[x].fa = mroot; connect(b,y,yson); connect(y,x,yson ^ 1); } void splay(int x) { int top = 0; st[++top] = x; for(int i = x;!isroot(i);i = a[i].fa) { st[++top] = a[i].fa; // cout<<"gg"<<endl; } // cout<<"out"<<endl; for(int i = top;i;i--) push_down(st[i]); while(!isroot(x)) { int y = a[x].fa; if(isroot(y)) rotate(x); else if(iden(x) == iden(y)) { rotate(y);rotate(x); } else { rotate(x);rotate(x); } // cout<<"233"<<endl; } } void access(int x) { int t = 0; while(x) { splay(x); a[x].ch[1] = t; t = x; x = a[x].fa; } } void rever(int x) { access(x); splay(x); a[x].rev ^= 1; } void link(int x,int y) { rever(x);a[x].fa = y; splay(x); // cout<<x<<" "<<y<<endl; } void cut(int x,int y) { rever(x); access(y); splay(y); a[y].ch[0] = a[x].fa = 0; } int find(int x) { // cout<<x<<endl; access(x);//cout<<"yes"<<endl; splay(x); int y = x; //cout<<"!!!"<<y<<endl; while(a[y].ch[0]) y = a[y].ch[0]; // cout<<y<<endl; return y; } int main() { // freopen("2147.in","r",stdin); char ch[10]; int x,y; read(n);read(m); duke(i,1,m) { scanf("%s",ch); read(x);read(y); if(ch[0] == 'C') link(x,y); else if(ch[0] == 'D') cut(x,y); else { if(find(x) == find(y)) printf("Yes "); else printf("No "); } } return 0; }