http://www.lydsy.com/JudgeOnline/problem.php?id=3282
复习了下lct,发现两个问题。。
1:一开始我以为splay那里直接全部rot(x)就好了,然后改了好几题lct的题,都过了且速度和原版一样。。然后怀疑了下。。。。。。后来请教神犇,他说这样不行。。(这是单旋了?时间复杂度不保证,,但是我还不知道反例)
2:findroot操作里不要使用makeroot后再找root。。。。。。。。。。。。。。。。。。。。。。多么的sb啊。。。。。。。。
然后就是裸的lct。
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; } #define printarr1(a, b) for1(_, 1, b) cout << a[_] << ' '; cout << endl inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=300005; struct node *null; struct node { int v, rev, w; node *ch[2], *fa; node(const int _v=0) : v(_v), rev(0), w(0) { ch[0]=ch[1]=fa=null; } bool d() { return fa->ch[1]==this; } bool check() { return fa->ch[0]!=this && fa->ch[1]!=this; } void setc(node* c, int d) { ch[d]=c; c->fa=this; } void pushup() { w=ch[0]->w^ch[1]->w^v; } void pushdown() { if(rev) { ch[0]->rev^=1; ch[1]->rev^=1; swap(ch[0], ch[1]); rev=0; } } }*t[N]; void rot(node* x) { node* fa=x->fa; bool d=x->d(); fa->pushdown(); x->pushdown(); if(!fa->check()) fa->fa->setc(x, fa->d()); else x->fa=fa->fa; fa->setc(x->ch[!d], d); x->setc(fa, !d); fa->pushup(); } void fix(node* x) { if(!x->check()) fix(x->fa); x->pushdown(); } void splay(node* x) { fix(x); while(!x->check()) if(x->fa->check()) rot(x); else x->d()==x->fa->d()?(rot(x->fa), rot(x)):(rot(x), rot(x)); x->pushup(); } node* access(node* x) { node* y=null; for(; x!=null; y=x, x=x->fa) { splay(x); x->ch[1]=y; } return y; } void mkroot(node* x) { access(x)->rev^=1; splay(x); } void link(node* x, node* y) { mkroot(x); x->fa=y; } void cut(node* x, node* y) { mkroot(x); access(y); splay(y); y->ch[0]->fa=null; y->ch[0]=null; } node* findrt(node* x) { access(x); splay(x); while(x->ch[0]!=null) x=x->ch[0]; return x; } void init() { null=new node; null->ch[0]=null->ch[1]=null->fa=null; } int n, m; int main() { init(); read(n); read(m); for1(i, 1, n) t[i]=new node(getint()); rep(i, m) { int c=getint(), x=getint(), y=getint(); if(c==0) { mkroot(t[x]); access(t[y]); splay(t[y]); printf("%d ", t[y]->w); } else if(c==1) { if(findrt(t[x])!=findrt(t[y])) link(t[x], t[y]); } else if(c==2) { if(findrt(t[x])==findrt(t[y])) cut(t[x], t[y]); } else if(c==3) { mkroot(t[x]); t[x]->v=y; t[x]->pushup(); } } return 0; }
Description
给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。
0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。
1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。
2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
3:后接两个整数(x,y),代表将点X上的权值变成Y。
Input
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
Output
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
1
HINT
1<=N,M<=300000