BZOJ_3282_Tree_LCT

BZOJ_3282_Tree_LCT

Description

Given N points and a weight for each point, you are asked to handle the next M operations.
There are 4 types of operations. Operations are numbered from 0 to 3. Points are numbered from 1 to N.
0: followed by two integers (x, y) representing the xor sum of the weights of the points on the path from x to y.
Ensure that x to y are connected.
1: Followed by two integers (x, y), representing the connection between x and y. If x and Y are already connected, no connection is required.
2: Followed by two integers (x, y), representing the deletion of the edge (x, y), the existence of the edge (x, y) is not guaranteed.
3: Followed by two integers (x, y), which represent changing the weight on point X to Y.

Input

The first line of two integers, respectively N and M, represent the number of points and operands.
Lines 2 to N+1, each line is an integer, the integer is in [1,10^9], representing the weight of each point.
Lines N+2 to N+M+1, each line has three integers, representing the operation type and the amount required for the operation.
1<=N,M<=300000

 

 

Output

For each operation 0, you must output the Xor sum of the point weights on the path from X to Y.

Sample Input

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

Sample Output

3
1

 LCT maintains the xor sum of the point weight, and a single point of modification is directly violent.
When modifying, access should not be used, but if I add access, the operation will be faster
 
Code:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 300050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int ch[N][2],f[N],sum[N],n,m,val[N],rev[N];
inline bool isrt(int p) {
    return ch[f[p]][1]!=p&&ch[f[p]][0]!=p;
}
inline void pushdown(int p) {
    if(rev[p]) {
        swap(ch[ls][0],ch[ls][1]);
        swap(ch[rs][0],ch[rs][1]);
        rev[ls]^=1; rev[rs]^=1;
        rev[p]=0;
    }
}
inline void pushup(int p) {
    sum[p]=sum[ls]^sum[rs]^val[p];
}
inline void update(int p) {
    if(!isrt(p)) update(f[p]);
    pushdown(p);
}
void rotate(int x) {
    int y=f[x],z=f[y],k=get(x);
    if(!isrt(y)) ch[z][ch[z][1]==y]=x;
    ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
    ch[x][!k]=y; f[y]=x; f[x]=z;
    pushup(y); pushup(x);
}
void splay(int x) {
    update(x);
    for(int fa;fa=f[x],!isrt(x);rotate(x))
        if(!isrt(fa))
            rotate(get(fa)==get(x)?fa:x);
}
void access(int p) {
    int t=0;
    while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot (int p) {
    access(p); splay(p);
    swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
    makeroot (x); f [x] = p;
}
void cut(int x,int p) {
    makeroot(x); access(p); splay(p); ls=f[x]=0;
}
int find(int p) {
    access(p); splay(p);
    while(ls) pushdown(p),p=ls;
    return p;
}
void fix(int x,int v) {
    /*access(x);*/ splay(x); sum[x]^=val[x]; val[x]=v; sum[x]^=val[x];
}
int main() {
    scanf("%d%d",&n,&m);
    int i,x,y,opt;
    for(i=1;i<=n;i++) scanf("%d",&val[i]);
    for(i=1;i<=m;i++) {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==0) {
            makeroot(x); access(y); splay(y);
            printf("%d\n",sum[y]);
        }else if(opt==1) {
            int t1=find(x),t2=find(y);
            if(t1!=t2) link(x,y);
        }else if(opt==2) {
            int t1=find(x),t2=find(y);
            if(t1==t2) cut(x,y);
        }else {
            fix(x,y);
        }
    }
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325084791&siteId=291194637