【洛谷P3690】【模板】Link Cut Tree

  • Post author:
  • Post category:其他


题目背景

动态树

题目描述

给定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<=N,M<=300000

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 300005
int fa[N],rev[N],xr[N],v[N],c[N][2],q[N];
int n,m;
using namespace std;
inline int read()
{
    int x=0;char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
inline bool isroot(int x)
{
    return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
inline void pushdown(int x)
{
    int l=c[x][0],r=c[x][1];
    if (rev[x])
    {
        rev[x]^=1;rev[l]^=1;rev[r]^=1;
        swap(c[x][0],c[x][1]);
    }
}
inline void update(int x)
{
    xr[x]=v[x]^xr[c[x][0]]^xr[c[x][1]];
}
inline void rotate(int x)
{
    int l,r,y=fa[x],z=fa[y];
    if (c[y][0]==x) l=0;else l=1;r=l^1;
    if (!isroot(y))
    {
        if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
    }
    fa[x]=z;fa[y]=x;
    fa[c[x][r]]=y;
    c[y][l]=c[x][r];
    c[x][r]=y;
    update(y);update(x);
} 
inline void splay(int x)
{
    int top=0;
    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))
        {
            if (c[z][0]==y^c[y][0]==x) rotate(x);else rotate(y);
        }
        rotate(x);
    }
}
inline void access(int x)
{
    int t=0;
    while (x)
    {
        splay(x);
        c[x][1]=t;
        update(x);
        t=x;
        x=fa[x];
    }
}
inline void makeroot(int x)
{
    access(x);
    splay(x);
    rev[x]^=1;
}
int find(int x)
{
    access(x);
    splay(x);
    while (c[x][0]) x=c[x][0];
    return x;
}
inline void link(int x,int y)
{
    makeroot(x);
    fa[x]=y;
}
inline void cut(int x,int y)
{
    makeroot(x);
    access(y);
    splay(y);
    if (c[y][0]!=x) return;
    fa[x]=0;
    c[y][0]=0;
    update(y);
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++)
        v[i]=read(),xr[i]=v[i];
    int opt,x,y;
    while (m--)
    {
        opt=read();x=read();y=read();
        if (opt==0)
        {
            makeroot(x);
            access(y);
            splay(y);
            printf("%d\n",xr[c[y][0]]^v[y]);
        }
        else if (opt==1)
        {
            if (find(x)!=find(y)) link(x,y);
        }
        else if (opt==2)
        {
            cut(x,y);
        }
        else
        {
            access(x);
            splay(x);
            v[x]=y;
            xr[x]=xr[c[x][0]]^v[x];
        }
    }
    return 0;
}



版权声明:本文为w_yqts原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。