LCT入门

什么都不想写了,

看大佬们的博客吧QAQ

题目背景

动态树

题目描述

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

输入输出样例

putin

3 3 
1
2
3
1 1 2
0 1 2 
0 1 1

putout

1

#include<bits/stdc++.h>
#define re return
#define ls c[x][0]
#define rs c[x][1] 
#define Ri register int
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int  maxn=3e5+5;
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1l;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

int q[maxn],n,m,c[maxn][2],val[maxn],ans[maxn],f[maxn];
bool rev[maxn];
inline bool nrt(int x)
{
    re c[f[x]][0]==x||c[f[x]][1]==x;
}

inline void pushup(int x)
{
    ans[x]=ans[ls]^ans[rs]^val[x];
}

inline void filp(int x)
{
    rev[x]^=1;
    swap(ls,rs);
}

inline void pushrev(int x)
{
    if(!rev[x])re;
    rev[x]=0;
    if(ls)filp(ls);
    if(rs)filp(rs);
}

inline void rotate(int x)
{
    int y=f[x],z=f[y],k=(c[y][1]==x),w=c[x][!k];
    if(nrt(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
    if(w)f[w]=y;f[x]=z;f[y]=x;
    pushup(y),pushup(x);
}

inline void splay(int x)
{
    int y=x,top=0;q[++top]=y;
    while(nrt(y))q[++top]=y=f[y];
    while(top)pushrev(q[top--]);
    while(nrt(x))
    {
        y=f[x],top=f[y];
        if(nrt(y))
        ((c[y][0]==x)&&(c[top][0]==y))?rotate(y):rotate(x);
        rotate(x);
    }
    //pushup(x)
}

inline void Access(int x)//将x->rt改为实边 
{
    for(Ri y=0;x;x=f[y=x])
    {
        splay(x);
        c[x][1]=y;
        pushup(x);
    }
}
inline void makert(int x)//使rt变为rt 
{
    Access(x);splay(x);
    filp(x);//降低复杂度 
}

inline int findrt(int x)//寻找根节点 
{
    Access(x);splay(x);
    while(ls)pushrev(x),x=ls;
    re x;
}

inline void split(int x,int y)//将x,y弄到同一棵splay 
{
    makert(x);Access(y);splay(y);
}

inline void link(int x,int y)
{
    makert(x);
    if(findrt(y)!=x)f[x]=y; 
}

inline void cut(int x,int y)
{
    split(x,y);
    if(findrt(y)!=x||f[x]!=y||rs) re;
    else 
    {
        f[x]=c[y][0]=0;
        pushup(y);
    }
}
int main()
{
    int opt,x,y;
    rd(n),rd(m);
    inc(i,1,n)rd(val[i]);
    inc(i,1,m)
    {
        rd(opt);rd(x),rd(y);
        switch(opt){
            
            case 0:split(x,y);printf("%d
",ans[y]);break;
            case 1:link(x,y);break;
            case 2:cut(x,y);break;
            case 3:splay(x);val[x]=y;break;
        }
    }
    re 0;
}
原文地址:https://www.cnblogs.com/lsyyy/p/11298459.html