UOJ207 共价大爷游长沙

神仙题!

我们考虑一条边被所有路径经过,那么以这条边的一个端点为根,所有路径都恰有一个端点落在另一个端点为根的子树中。

这个过程我们用哈希随机一个数值维护异或和就可以了。

然后就是标准的子树信息LCT啦。

我个睿智忘了写push...以为写错了,然后看标程改改改以为过不了第二个样例,实际上是太长了没显示出来...

把最开始的代码加了个push也过了...哭(

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 300010
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define fa(x) t[x].fa
#define nrt(x) (ls(fa(x))==x||rs(fa(x))==x)
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct node{int fa,son[2],cnt,sum; bool tag;}t[N];
int a[N];
void pushup(int x){t[x].sum=a[x]^t[x].cnt^t[ls(x)].sum^t[rs(x)].sum;}
void rotate(int x)
{
    if(!nrt(x)||!x)    return;
    int f=fa(x),gf=fa(f);
    int k=rs(f)==x,p=k^1;
    if(nrt(f))    t[gf].son[rs(gf)==f]=x;
    if(t[x].son[p])    t[t[x].son[p]].fa=f;
    t[f].son[k]=t[x].son[p]; t[x].son[p]=f;
    t[x].fa=gf; t[f].fa=x;
    pushup(f); pushup(x);
}
void pushdown(int x)
{
    if(t[x].tag)
    {
        swap(ls(x),rs(x));
        if(ls(x))    t[ls(x)].tag^=1;
        if(rs(x))    t[rs(x)].tag^=1;
        t[x].tag=0;
    }
}
void push(int x)
{
    if(nrt(x))    push(fa(x));
    pushdown(x);
}
void splay(int x)
{
    push(x);
    while(nrt(x))
    {
        int f=fa(x),gf=fa(f);
        if(nrt(gf))    rotate((rs(gf)==f)^(rs(f)==x)?x:f);
        rotate(x);
    }
}
void access(int x)
{
    int y=0;
    do
    {
        splay(x); t[x].cnt^=t[y].sum^t[rs(x)].sum;
        t[x].son[1]=y; pushup(x); y=x; x=fa(x);
    }while(x);
}
void makeroot(int x)
{
    access(x); splay(x); t[x].tag=1;
}
int findroot(int x)
{
    access(x); splay(x);
    while(ls(x)) x=ls(x);
    return x;
}
void split(int x,int y)
{
    makeroot(x); access(y); splay(y);
}
void cut(int x,int y)
{
    split(x,y); t[y].son[0]=t[x].fa=0; pushup(y); pushup(x);
}
void link(int x,int y)
{
    split(x,y);
    if(findroot(y)==x)    return;
    t[y].cnt^=t[x].sum; t[x].fa=y;
}
int my_rand()
{
    return rand()<<15|rand();
}
int val,V[N],tot,X[N],Y[N];
int main()
{
    int id=read(); srand(20021225);
    int n=read(),m=read();
    for(int i=1;i<n;i++)
    {
        int x=read(),y=read();
        link(x,y);
    }
    while(m--)
    {
        int opt=read();
        if(opt==1)
        {
            int x=read(),y=read(),u=read(),v=read();
            cut(x,y); link(u,v);
        }
        else if(opt==2)
        {
            int x=read(),y=read();
            int v=my_rand();
            V[++tot]=v; X[tot]=x; Y[tot]=y;
            access(x); splay(x); a[x]^=v; pushup(x);
            access(y); splay(y); a[y]^=v; pushup(y);
            val^=v;
        }
        else if(opt==3)
        {
            int p=read(),v=V[p],x=X[p],y=Y[p];
            access(x); splay(x); a[x]^=v; pushup(x);
            access(y); splay(y); a[y]^=v; pushup(y);
            val^=v;
        }
        else if(opt==4)
        {
            int x=read(),y=read(); split(x,y);
            puts(t[x].sum==val?"YES":"NO");
        }
    }
    return 0;
}
View Code

 

posted @ 2019-09-27 13:59  寒雨微凝  阅读(185)  评论(0编辑  收藏  举报