[bzoj3282]Tree (lct)
昨天看了一天的lct。。当然幸好最后看懂了(也许吧。。)
论善良学长的重要性T_T,老司机带带我!
这题主要是删边的时候还要判断一下。。蒟蒻一开始天真的以为存在的边才能删结果吃了一发wa。。。
事实是只要两个点之间联通就能断开了,管它有没有边。。。。整个就一模板题。。
交上去后跑得很慢(记录类型的锅)。。但还是很短?(请自行无视过长变量名)
1 #include<cstdio> 2 #include<math.h> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=300233; 7 struct zs{ 8 int c[2],fa,val,sum; 9 bool rev; 10 }tree[maxn]; 11 int i,j,n,m,id,x,y; 12 int stack[maxn]; 13 inline void update(int x){tree[x].sum=tree[tree[x].c[0]].sum^tree[x].val^tree[tree[x].c[1]].sum; 14 } 15 inline bool isroot(int x){return tree[tree[x].fa].c[0]!=x&&tree[tree[x].fa].c[1]!=x; 16 } 17 void rotate(int x){ 18 int fa=tree[x].fa,gfa=tree[fa].fa; 19 if(!isroot(fa))tree[gfa].c[tree[gfa].c[1]==fa]=x; 20 int l=tree[fa].c[1]==x,r=l^1; 21 tree[fa].c[l]=tree[x].c[r];tree[x].c[r]=fa; 22 tree[fa].fa=x;tree[x].fa=gfa;tree[tree[fa].c[l]].fa=fa; 23 update(fa);update(x); 24 } 25 void pushdown(int x){ 26 if(!tree[x].rev)return; 27 int l=tree[x].c[0],r=tree[x].c[1]; 28 if(l)tree[l].rev^=1;if(r)tree[r].rev^=1; 29 swap(tree[x].c[0],tree[x].c[1]);tree[x].rev^=1; 30 } 31 void splay(int x){ 32 int top=0,tmp=x;stack[++top]=x; 33 while(!isroot(tmp))stack[++top]=tree[tmp].fa,tmp=tree[tmp].fa; 34 while(top)pushdown(stack[top]),top--; 35 int fa,gfa; 36 while(!isroot(x)){ 37 fa=tree[x].fa,gfa=tree[fa].fa; 38 if(!isroot(fa)) 39 if((tree[gfa].c[0]==fa)^(tree[fa].c[0]==x))rotate(x); 40 else rotate(fa); 41 rotate(x); 42 } 43 } 44 void access(int x){ 45 int son=0; 46 while(x){ 47 splay(x);tree[x].c[1]=son; 48 update(x); 49 son=x;x=tree[x].fa; 50 } 51 } 52 void makeroot(int x){ 53 access(x);splay(x);tree[x].rev^=1; 54 } 55 void link(int x,int y){ 56 makeroot(x);tree[x].fa=y;splay(x); 57 } 58 void cut(int x,int y){ 59 makeroot(x);access(y);splay(y);tree[y].c[0]=tree[x].fa=0; 60 } 61 int query(int x,int y){ 62 makeroot(x);access(y);splay(y);return tree[y].sum; 63 } 64 int getfa(int x){ 65 access(x);splay(x);while(tree[x].c[0])pushdown(x),x=tree[x].c[0];splay(x); 66 return x; 67 } 68 void change(int x,int y){ 69 makeroot(x);tree[x].val=y;update(x); 70 } 71 int main(){ 72 scanf("%d%d",&n,&m); 73 for(i=1;i<=n;i++)scanf("%d",&tree[i].val),tree[i].sum=tree[i].val; 74 while(m--){ 75 scanf("%d%d%d",&id,&x,&y); 76 if(id==0)printf("%d\n",query(x,y)); 77 else if(id==1){if(getfa(x)!=getfa(y))link(x,y);} 78 else if(id==2){if(getfa(x)==getfa(y))cut(x,y);} 79 else if(id==3)change(x,y); 80 } 81 return 0; 82 }
b站上的lct怎么都是300大洋的世界。。
16.1.13:重写了一发
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=300233; 6 int ch[maxn][2],fa[maxn],sum[maxn],num[maxn],st[maxn]; 7 bool rev[maxn]; 8 int i,j,n,m,x,y; 9 10 int ra;char rx; 11 inline int read(){ 12 rx=getchar(),ra=0; 13 while(rx<'0'||rx>'9')rx=getchar(); 14 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 15 } 16 char s[11]; 17 inline void outx(int x){ 18 if(!x)putchar('0'); 19 register int len=0; 20 while(x)s[++len]=x%10,x/=10; 21 while(len)putchar(s[len--]+48);putchar('\n'); 22 } 23 inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} 24 inline void upd(int x){sum[x]=sum[ch[x][0]]^num[x]^sum[ch[x][1]];} 25 inline void pushdown(int x){ 26 if(!rev[x])return; 27 rev[x]=0,swap(ch[x][0],ch[x][1]),rev[ch[x][0]]^=1,rev[ch[x][1]]^=1; 28 } 29 inline void rotate(int x){ 30 int f=fa[x],gfa=fa[f],l=ch[f][1]==x,r=l^1; 31 if(!isrt(f))ch[gfa][ch[gfa][1]==f]=x; 32 fa[x]=gfa,fa[f]=x,ch[f][l]=ch[x][r],ch[x][r]=f,fa[ch[f][l]]=f; 33 sum[x]=sum[f],upd(f); 34 } 35 void splay(int x){ 36 int f,gfa; 37 for(st[st[0]=1]=f=x;!isrt(f);)st[++st[0]]=(f=fa[f]); 38 while(st[0])pushdown(st[st[0]--]); 39 for(f=fa[x],gfa=fa[f];!isrt(x);rotate(x),f=fa[x],gfa=fa[f]) 40 if(!isrt(f))rotate(((ch[f][0]==x)^(ch[gfa][0]==f))?x:f); 41 } 42 inline void access(int x){ 43 for(int t=0;x;t=x,x=fa[x])splay(x),ch[x][1]=t,upd(x); 44 } 45 inline void makert(int x){ 46 access(x),splay(x),rev[x]^=1; 47 } 48 void cut(int x,int y){ 49 makert(x),access(y),splay(y),ch[y][0]=fa[x]=0,upd(y); 50 } 51 void link(int x,int y){ 52 makert(x),fa[x]=y;if(!(x&233))splay(x); 53 } 54 inline int query(int x,int y){ 55 makert(x),access(y),splay(y); 56 return sum[y]; 57 } 58 inline int getfa(int x){ 59 for(access(x),splay(x),pushdown(x);ch[x][0];x=ch[x][0]); 60 return x; 61 } 62 inline void change(int x,int v){ 63 splay(x),num[x]=v,upd(x); 64 } 65 int main(){ 66 n=read(),m=read(); 67 for(i=1;i<=n;i++)num[i]=read();int id; 68 while(m--){ 69 id=read(),x=read(),y=read(); 70 if(id==0)outx(query(x,y)); 71 if(id==1)if(getfa(x)!=getfa(y))link(x,y); 72 if(id==2)if(getfa(x)==getfa(y))cut(x,y); 73 if(id==3)change(x,y); 74 } 75 return 0; 76 }
3282: Tree
Time Limit: 30 Sec Memory Limit: 512 MB
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