[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
",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 }
View Code

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('
');
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 }
View Code

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
 

Sample Output

3
1
 

HINT

1<=N,M<=300000

原文地址:https://www.cnblogs.com/czllgzmzl/p/4723225.html