码迷,mamicode.com
首页 > 其他好文 > 详细

[lct] Luogu P3690【模板】Link Cut Tree (动态树)

时间:2019-07-03 21:33:22      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:turn   hup   模板   动态   ADG   范围   ota   tag   int   

题目描述

给定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。

输入输出格式

输入格式:

 

第1行两个整数,分别为n和m,代表点数和操作数。

第2行到第n+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

第n+2行到第n+m+1行,每行三个整数,分别代表操作类型和操作所需的量。

 

输出格式:

 

对于每一个0号操作,你须输出x到y的路径上点权的xor和。

 

输入输出样例

输入样例#1:
3 3 
1
2
3
1 1 2
0 1 2 
0 1 1
输出样例#1:
3
1

说明

数据范围: 1 \leq N, M \leq 3 \cdot {10}^51N,M3105

 

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define N 300010
 5 using namespace std;
 6 int n,m,f[N],ch[N][2],v[N],s[N],st[N],tag[N];
 7 int nroot(int x) { return ch[f[x]][0]==x||ch[f[x]][1]==x; }
 8 void pushup(int x) { s[x]=s[ch[x][0]]^s[ch[x][1]]^v[x]; }
 9 void swap(int x) { ch[x][0]^=ch[x][1],ch[x][1]^=ch[x][0],ch[x][0]^=ch[x][1],tag[x]^=1; }
10 void pushdown(int x) { if (tag[x]) swap(ch[x][0]),swap(ch[x][1]),tag[x]=0; }
11 void rotate(int x)
12 {
13     int y=f[x],z=f[y],k=ch[y][1]==x,w=ch[x][!k];
14     if (nroot(y)) ch[z][ch[z][1]==y]=x;
15     ch[x][!k]=y,ch[y][k]=w,f[y]=x,f[x]=z;
16     if (w) f[w]=y;
17     pushup(y);
18 }
19 void splay(int x)
20 {
21     int y=x,r=0; st[++r]=y;
22     while (nroot(y)) st[++r]=y=f[y];
23     while (r) pushdown(st[r--]);
24     while (nroot(x))
25     {
26         y=f[x],r=f[y];
27         if (nroot(y)) (ch[r][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
28         rotate(x);
29     }
30     pushup(x);
31 }
32 void access(int x) { for (int y=0;x;x=f[y=x]) splay(x),ch[x][1]=y,pushup(x); }
33 void makeroot(int x) { access(x),splay(x),swap(x); }
34 int findroot(int x)
35 {
36     makeroot(x),splay(x);
37     while (ch[x][0]) x=ch[x][0],pushdown(x);
38     splay(x); return x;
39 }
40 void split(int x,int y) { makeroot(x),access(y),splay(y); }
41 void link(int x,int y) { makeroot(x); if (findroot(y)!=x) f[x]=y; }
42 void cut(int x,int y) { split(x,y); if (ch[y][0]==x) f[x]=ch[y][0]=0,pushup(y); }
43 int main()
44 {
45     scanf("%d%d",&n,&m);
46     for (int i=1;i<=n;i++) scanf("%d",&v[i]);
47     for (int op,x,y;m;m--)
48     {
49         scanf("%d%d%d",&op,&x,&y);
50         if (op==0) split(x,y),printf("%d\n",s[y]);
51         if (op==1) link(x,y);
52         if (op==2) cut(x,y);
53         if (op==3) splay(x),v[x]=y;
54     }
55 }

 

[lct] Luogu P3690【模板】Link Cut Tree (动态树)

标签:turn   hup   模板   动态   ADG   范围   ota   tag   int   

原文地址:https://www.cnblogs.com/Comfortable/p/11129186.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!