天天看點

BZOJ 3282 Tree link cut trees

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

​​傳送門​​

竟然找到水題了……

結果洛谷上有這題,竟然貼了個很老舊的……于是大緻整改了一下。

#include<bits/stdc++.h>
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int 
    N=300005;
int n,m;
struct LCT{
    int val,xsum,pre,son[2];
    bool rev;
}tree[N];
bool isroot(int x){
    return tree[tree[x].pre].son[0]!=x &&
           tree[tree[x].pre].son[1]!=x;
}
void up(int x){
    if (x){
        tree[x].xsum=tree[x].val;
        if (tree[x].son[0]) tree[x].xsum^=tree[tree[x].son[0]].xsum;
        if (tree[x].son[1]) tree[x].xsum^=tree[tree[x].son[1]].xsum;
    }
}
void down(int x){
    if (x && tree[x].rev){
        swap(tree[x].son[0],tree[x].son[1]);
        tree[tree[x].son[0]].rev^=1;
        tree[tree[x].son[1]].rev^=1;
        tree[x].rev^=1;
    }
}
void Rotate(int x){  
    int y=tree[x].pre,z=tree[y].pre,l,r;  
    if (tree[y].son[0]==x) l=0; else l=1;  
    r=l^1;  
    if (!isroot(y))  
        if (tree[z].son[0]==y) tree[z].son[0]=x;  
            else tree[z].son[1]=x;  
    tree[x].pre=z,tree[y].pre=x;  
    tree[y].son[l]=tree[x].son[r];  
    tree[tree[x].son[r]].pre=y;  
    tree[x].son[r]=y;  
    up(y);  
}  
int stk[N];  
void splay(int x){  
    int top=1;stk[1]=x;  
    for (int i=x;!isroot(i);i=tree[i].pre)  
        stk[++top]=tree[i].pre;  
    while (top) down(stk[top--]);  
    while (!isroot(x)){  
        int y=tree[x].pre,z=tree[y].pre;  
        if (!isroot(y))  
            if (tree[y].son[0]==x^tree[z].son[0]==y) Rotate(x);  
                else Rotate(y);  
        Rotate(x);  
    }  
    up(x);  
}  
void access(int x){
    for (int t=0;x;t=x,x=tree[x].pre)
        splay(x),tree[x].son[1]=t,up(x);
}
void makeroot(int x){
    access(x),splay(x);
    tree[x].rev^=1;
}
int findroot(int x){
    access(x),splay(x);
    while (tree[x].son[0]) x=tree[x].son[0];
    return x;
}
void split(int x,int y){
    makeroot(x);
    access(y),splay(y); 
}
void cut(int x,int y){
    split(x,y);
    tree[y].son[0]=tree[x].pre=0;
}
void link(int x,int y){
    makeroot(x);
    tree[x].pre=y;
}
int main(){
    n=read(),m=read();
    for (int i=1;i<=n;i++) tree[i].val=tree[i].xsum=read();
    int opt,x,y;
    while (m--){
        opt=read(),x=read(),y=read();
        if (!opt){
            split(x,y);
            printf("%d\n",tree[y].xsum);
        }
        if (opt==1 && findroot(x)!=findroot(y)) link(x,y);
        if (opt==2 && findroot(x)==findroot(y)) cut(x,y);
        if (opt==3){
            access(x),splay(x);
            tree[x].val=y;
            up(x);
        }
    }
    return 0;
}      
上一篇: 安裝vue3
下一篇: Vue3配置路由

繼續閱讀