Evanyou Blog 彩带

洛谷P3690 [模板] Link Cut Tree [LCT]

  题目传送门

Link Cut Tree

题目背景

动态树

题目描述

给定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 · $ 10^5 $


  分析:

  Link Cut Tree模板题。具体的知识点这位大佬已经讲的特别好了,推荐这位大佬的博客<http://www.cnblogs.com/flashhu/p/8324551.html>,蒟蒻就只放代码了。

  Code:

 

//It is made by HolseLee on 27th June 2018
//Luogu.org P3690
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
int n,m,val[N];
struct LCT{
    int fa[N],ch[N][2],xr[N],sign[N],q[N],top;
    inline void pushup(int u)
    {
        xr[u]=xr[ch[u][0]]^xr[ch[u][1]]^val[u];
    }
    inline void change(int u)
    {
        int temp=ch[u][0];
        ch[u][0]=ch[u][1];
        ch[u][1]=temp;
        sign[u]^=1;
    }
    inline void pushdown(int u)
    {
        if(!sign[u])return;
        if(ch[u][0])change(ch[u][0]);
        if(ch[u][1])change(ch[u][1]);
        sign[u]=0;
    }
    inline bool isroot(int u)
    {
        return (ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u);
    }
    inline void rotate(int x)
    {
        int y=fa[x],z=fa[y];
        int k=(ch[y][1]==x);
        int w=ch[x][k^1];
        if(!isroot(y))ch[z][ch[z][1]==y]=x;
        ch[x][k^1]=y;ch[y][k]=w;
        if(w)fa[w]=y;fa[y]=x;fa[x]=z;
        pushup(y);pushup(x);
    }
    inline void splay(int x)
    {
        top=1;q[top]=x;
        for(int i=x;!isroot(i);i=fa[i])
            q[++top]=fa[i];
        while(top)pushdown(q[top--]);
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y))
            (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int u)
    {
        for(int i=0;u;i=u,u=fa[u]){
        splay(u);ch[u][1]=i;pushup(u);}
    }
    void makeroot(int u)
    {
        access(u);splay(u);change(u);
    }
    inline int find(int u)
    {
        access(u);splay(u);
        while(ch[u][0])pushdown(u),u=ch[u][0];
        //splay(u);
        return u;
    }
    void split(int u,int v)
    {
        makeroot(u);access(v);splay(v);
    }
    void cut(int u,int v)
    {
        makeroot(u);
        if(find(v)==u&&fa[u]==v&&!ch[u][1]){
            fa[u]=ch[v][0]=0;pushup(v);}
    }
    void link(int u,int v)
    {
        makeroot(u);
        if(find(v)!=u)fa[u]=v;
    }
}T;
inline int read()
{
    char ch=getchar();int num=0;bool flag=false;
    while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
    while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
    return flag?-num:num;
}
int main()
{
    n=read();m=read();int opt,x,y;
    for(int i=1;i<=n;i++){
        val[i]=read();T.xr[i]=val[i];}
    for(int i=1;i<=m;i++){
        opt=read();x=read();y=read();
        if(opt==0){
            T.split(x,y);
            printf("%d\n",T.xr[y]);}
        else if(opt==1){T.link(x,y);}
        else if(opt==2){T.cut(x,y);}
        else if(opt==3){
        T.splay(x);val[x]=y;T.pushup(x);}
    }
    return 0;
} 

 

posted @ 2018-06-27 22:43  HolseLee  阅读(200)  评论(0编辑  收藏  举报