BZOJ3282: Tree

BZOJ3282: Tree

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行,每行三个整数,分别代表操作类型和操作所需的量。
1<=N,M<=300000

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
题解Here!
这个算是LCT板子题了吧。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 300010
using namespace std;
int n,m,val[MAXN];
int top=0,stack[MAXN];
struct Link_Cut_Tree{
    int son[2];
    int f,v,flag;
}a[MAXN];
inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    return date*w;
}
inline bool isroot(int rt){
    return a[a[rt].f].son[0]!=rt&&a[a[rt].f].son[1]!=rt;
}
inline void pushup(int rt){
    if(!rt)return;
    a[rt].v=val[rt]^a[a[rt].son[0]].v^a[a[rt].son[1]].v;
}
inline void pushdown(int rt){
    if(!rt||!a[rt].flag)return;
    a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
    swap(a[rt].son[0],a[rt].son[1]);
}
inline void turn(int rt){
    int x=a[rt].f,y=a[x].f,k=a[x].son[0]==rt?1:0;
    if(!isroot(x)){
        if(a[y].son[0]==x)a[y].son[0]=rt;
        else a[y].son[1]=rt;
    }
    a[rt].f=y;a[x].f=rt;a[a[rt].son[k]].f=x;
    a[x].son[k^1]=a[rt].son[k];a[rt].son[k]=x;
    pushup(x);pushup(rt);
}
void splay(int rt){
    top=0;
    stack[++top]=rt;
    for(int i=rt;!isroot(i);i=a[i].f)stack[++top]=a[i].f;
    while(top)pushdown(stack[top--]);
    while(!isroot(rt)){
        int x=a[rt].f,y=a[x].f;
        if(!isroot(x)){
            if((a[y].son[0]==x)^(a[x].son[0]==rt))turn(rt);
            else turn(x);
        }
        turn(rt);
    }
}
inline void access(int rt){
    for(int i=0;rt;i=rt,rt=a[rt].f){
        splay(rt);
        a[rt].son[1]=i;
        pushup(rt);
    }
}
inline void makeroot(int rt){access(rt);splay(rt);a[rt].flag^=1;}
int find(int rt){
    access(rt);splay(rt);
    while(a[rt].son[0])rt=a[rt].son[0];
    return rt;
}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void link(int x,int y){makeroot(x);a[x].f=y;}
inline void cut(int x,int y){
    split(x,y);
    if(a[y].son[0]==x&&a[x].f==y&&!a[x].son[1])a[y].son[0]=a[x].f=0;
}
inline int query(int x,int y){split(x,y);return a[y].v;}
void work(){
    int f,x,y;
    while(m--){
        f=read();x=read();y=read();
        switch(f){
            case 0:printf("%d\n",query(x,y));break;
            case 1:{
                int fx=find(x),fy=find(y);
                if(fx!=fy)link(x,y);
                break;
            }
            case 2:{
                int fx=find(x),fy=find(y);
                if(fx==fy)cut(x,y);
                break;
            }
            case 3:access(x);splay(x);val[x]=y;pushup(x);break;
        }
    }
}
void init(){
    n=read();m=read();
    for(int i=1;i<=n;i++)val[i]=read();
}
int main(){
    init();
    work();
    return 0;
}

 

posted @ 2018-07-26 19:14  符拉迪沃斯托克  阅读(169)  评论(0编辑  收藏  举报
Live2D