UOJ #207 共价大爷游长沙 - LCT

(为啥我傻了吧唧的拆了点)
集合中的每一对点随即一个权值,然后再树上两个点分别异或这个权值,最后每次询问统计其中一边的子树的异或和是不是所有点对的权值的异或和即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<unordered_map>
#include<utility>
#include<assert.h>
#define uint unsigned long long
#define hv(x,y) ((uint)x*INT_MAX+y)
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define N 200010
#define M 300010
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct Rand{
    uint x;Rand(){x=1234567;}
    inline uint operator()()
    { return x=((x*2333333333+998244353)%1000000007)^12379713; }
}rnd;
unordered_map<uint,int> eid;pii sid[M];int pf[N];
uint s[N],val[N],sv[N];int fa[N],ch[N][2],rev[N];
inline int gw(int x) { return ch[fa[x]][1]==x; }
inline int push_up(int x) { return s[x]=val[x]^s[ch[x][0]]^s[ch[x][1]],0; }
inline int push_down(int x)
{
    if(ch[x][0]) rev[ch[x][0]]^=1;
    if(ch[x][1]) rev[ch[x][1]]^=1;
    return swap(ch[x][0],ch[x][1]),rev[x]=0;
}
inline int setc(int x,int y,int z)
{   if(!x) return fa[y]=0;ch[x][z]=y;if(y) fa[y]=x;return push_up(x);   }
inline int rotate(int x)
{
    int y=fa[x],z=fa[y],a=gw(x),b=gw(y),c=ch[x][a^1];
    return swap(pf[x],pf[y]),setc(y,c,a),setc(x,y,a^1),setc(z,x,b);
}
inline int all_down(int x) { return (fa[x]?all_down(fa[x]):0),(rev[x]?push_down(x):0); }
inline int splay(int x,int tar=0)
{
    for(all_down(x);fa[x]^tar;rotate(x))
        if(fa[fa[x]]) rotate((gw(x)^gw(fa[x]))?x:fa[x]);
    return 0;
}
inline int expose(int x)
{
    splay(x);int y=ch[x][1];if(!y) return 0;
    return pf[y]=x,fa[y]=ch[x][1]=0,val[x]^=s[y],push_up(x);
}
inline int splice(int x)
{
    splay(x);int y=pf[x];if(!y) return 0;
    return expose(y),splay(y),val[y]^=s[x],setc(y,x,1),pf[x]=0,1;
}
inline int access(int x) { expose(x);while(splice(x));return 0; }
inline int evert(int x) { return access(x),splay(x),rev[x]^=1; }
inline int link(int x,int y) { return evert(x),splay(x),evert(y),splay(y),pf[y]=x,val[x]^=s[y],s[x]^=s[y],0; }
inline int cut(int x,int y) { return evert(x),access(y),splay(x),s[x]^=s[y],ch[x][1]=fa[y]=pf[y]=0; }
inline int update(int x,uint v) { return access(x),splay(x),val[x]^=v,s[x]^=v,0; }
inline uint query(int x,int y,uint v=0) { return cut(x,y),evert(x),splay(x),v=s[x],link(x,y),v; }
int main()
{
    int Test_id=inn(),n=inn(),m=inn(),sc=0;uint tot_val=0;
    for(int i=1,x,y,c=n;i<n;i++)
        x=inn(),y=inn(),eid[hv(x,y)]=eid[hv(y,x)]=++c,link(x,c),link(c,y);
    while(m--)
    {
        int opt=inn(),x,y,u,v,c;
        if(opt==1) x=inn(),y=inn(),u=inn(),v=inn(),c=eid[hv(x,y)],
            cut(x,c),cut(c,y),link(u,c),link(c,v),eid[hv(u,v)]=eid[hv(v,u)]=c;
        else if(opt==2) x=inn(),y=inn(),sid[++sc]=mp(x,y),
            sv[sc]=rnd(),update(x,sv[sc]),update(y,sv[sc]),tot_val^=sv[sc];
        else if(opt==3) c=inn(),x=sid[c].fir,y=sid[c].sec,update(x,sv[c]),update(y,sv[c]),tot_val^=sv[c];
        else x=inn(),y=inn(),printf("%s\n",query(x,eid[hv(x,y)])==tot_val?"YES":"NO");
    }
    return Test_id-Test_id+0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值