Link-Cut-Tree 题目总结

P3690 【模板】Link Cut Tree (动态树)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=2e6+10;
int fa[N],val[N],sum[N],son[N][2],rev[N],st[N];
int get(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;}
void up(int x){sum[x]=sum[son[x][1]]^sum[son[x][0]]^val[x];}
void change(int x){swap(son[x][0],son[x][1]);rev[x]^=1;}
void down(int x)
{   
    if(!rev[x])return ;
    rev[x]=0;
    if(son[x][0])change(son[x][0]);
    if(son[x][1])change(son[x][1]);
}
void rotate(int x)
{
    int y=fa[x],z=fa[y],k=son[fa[x]][1]==x,w=son[x][k^1];
    if(get(y))son[z][son[z][1]==y]=x;son[x][k^1]=y;son[y][k]=w;
    if(w)fa[w]=y;fa[y]=x;fa[x]=z;
    up(y);up(x);
}
void splay(int x)
{
    int y=x,top=0;st[++top]=y;
    while(get(y))st[++top]=y=fa[y];
    while(top)down(st[top--]);
    while(get(x))
    {
        int y=fa[x],z=fa[y];
        if(get(y))
        rotate((son[y][0]==x)^(son[z][0]==y)?x:y);
        rotate(x);
    }up(x);
}
void access(int x)
{   
    for(int y=0;x;x=fa[y=x])
    splay(x),son[x][1]=y,up(x);
}
void makeroot(int x)
{
    access(x);splay(x);change(x);
}
int findroot(int x)
{
    access(x);splay(x);
    while(son[x][0])down(x),x=son[x][0];
    splay(x);return x;
}
void split(int x,int y)
{
    makeroot(x);access(y);splay(y);
}
void link(int x,int y)
{
    makeroot(x);if(findroot(y)!=x)fa[x]=y;
}
void cut(int x,int y)
{
    split(x,y);
    if(findroot(y)==x&&fa[y]==x&&!son[y][0])
    fa[y]=son[x][1]=0,up(x);
}int n,m,x,y,op;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&val[i]);
    while(m--)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(op==0)split(x,y),printf("%d\n",sum[y]);
        if(op==1)link(x,y);
        if(op==2)cut(x,y);
        if(op==3)splay(x),val[x]=y;//这里不up也没事 反正问的时候也会up
    }
    return 0;
}
View Code

P2147 [SDOI2008]洞穴勘测

题意: 就是可删除的并查集

题解: 没啥好说的 比模板简单

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
////////////////////////////////////
const int N=2e6+10;
int fa[N],son[N][2],rev[N],st[N];
int get(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;}
void change(int x){swap(son[x][1],son[x][0]);rev[x]^=1;}
void down(int x)
{
    if(!rev[x])return ;
    rev[x]=0;
    if(son[x][1])change(son[x][1]);
    if(son[x][0])change(son[x][0]);
}
void rotate(int x)
{
    int y=fa[x],z=fa[y],k=son[fa[x]][1]==x,w=son[x][k^1];
    if(get(y))son[z][son[z][1]==y]=x;son[x][k^1]=y;son[y][k]=w;
    if(w)fa[w]=y;fa[y]=x;fa[x]=z;
}
void splay(int x)
{   
    int y=x,top=0;st[++top]=y;
    while(get(y))st[++top]=y=fa[y];
    while(top)down(st[top--]);

    while(get(x))
    {
        int y=fa[x],z=fa[y];
        if(get(y))
        rotate((son[y][0]==x)^(son[z][0]==y)?x:y);
        rotate(x);
    }
}
void access(int x)
{
    for(int y=0;x;x=fa[y=x])
    splay(x),son[x][1]=y;
}
void makeroot(int x)
{
    access(x);splay(x);change(x);
}
int findroot(int x)
{
    access(x);splay(x);
    while(son[x][0])down(x),x=son[x][0];
    splay(x);return x;
}
void split(int x,int y)
{
    makeroot(x);access(y);splay(y);
}
void link(int x,int y)
{
    makeroot(x);
    if(findroot(y)!=x)fa[x]=y;
}
bool judge(int x,int y)
{
    makeroot(x);
    return findroot(y)==x;
}
void cut(int x,int y)
{
    split(x,y); 
    if(findroot(y)==x&&fa[y]==x&&!son[y][0])
    fa[y]=son[x][1]=0;
}char s[100];int n,m,x,y;
int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%s %d%d",s,&x,&y);
        if(s[0]=='Q')printf("%s\n",judge(x,y)?"Yes":"No");
        if(s[0]=='C')link(x,y);
        if(s[0]=='D')cut(x,y);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/bxd123/p/11626972.html