[BZOJ]3282: Tree lct

来源:互联网 发布:软件界面模糊 编辑:程序博客网 时间:2024/05/17 14:26

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。

题解:

LCT水题。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=300010;int n,m;int son[maxn][2],fa[maxn],s[maxn],sta[maxn],val[maxn];bool rev[maxn];void push_down(int x){    if(rev[x])    {        rev[x]=false;        swap(son[x][0],son[x][1]);        rev[son[x][0]]^=1;rev[son[x][1]]^=1;    }}void push_up(int x){s[x]=(val[x]^s[son[x][0]]^s[son[x][1]]);}bool is_root(int x){    if(son[fa[x]][0]==x)return false;    if(son[fa[x]][1]==x)return false;    return true;}void rotate(int x){    int y=fa[x],z=fa[y];    int a=son[y][1]==x,b=son[z][1]==y;    if(!is_root(y))son[z][b]=x;    fa[x]=z;    int g=son[x][!a];    son[y][a]=g;    fa[g]=y;    son[x][!a]=y;    fa[y]=x;    push_up(y);push_up(x);}void pre(int x){    if(!is_root(x))pre(fa[x]);    push_down(x);}void splay(int x){    pre(x);    while(!is_root(x))    {        int y=fa[x],z=fa[y];        if(!is_root(y))        {            if((son[z][1]==y)==(son[y][1]==x))rotate(y);            else rotate(x);        }        rotate(x);    }    push_up(x);}void access(int x){    int last=0;    while(x)    {        splay(x);        son[x][1]=last;        push_down(x);        last=x;        x=fa[x];    }}int find_root(int x){    access(x);splay(x);    while(son[x][0])x=son[x][0];    return x;}void make_root(int x){    access(x);splay(x);    rev[x]^=1;}void split(int x,int y)//y为的splay的根{    make_root(x);    access(y);    splay(y);   } void link(int x,int y)//y变为x父亲 {    if(find_root(x)==find_root(y))return;    make_root(x);fa[x]=y;}void cut(int x,int y){    if(find_root(x)!=find_root(y))return;    split(x,y);    fa[x]=son[y][0]=0;    push_up(y);}int query(int x,int y){    split(x,y);    return s[y];}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%d",&val[i]);        s[i]=val[i];    }    for(int i=1;i<=m;i++)    {        int op,x,y;        scanf("%d%d%d",&op,&x,&y);        if(op==0)printf("%d\n",query(x,y));        else if(op==1)link(x,y);        else if(op==2)cut(x,y);        else        {            make_root(x);            s[x]^=val[x];            val[x]=y;            s[x]^=val[x];        }    }}
原创粉丝点击