这道题思路方面就不多讲了,主要是通过这题学一下lct维护子树信息。

lct某节点u的子树信息由其重链的一棵splay上信息和若干轻儿子子树信息合并而成。

splay是有子树结构的,可以在rotate,access的时候由儿子update到父亲,而轻儿子的信息update不上来,需要另外记一下。

记sum[x]为我们要求的子树信息,xu[x]为x的轻儿子的子树信息。

(即,xu[x]由轻儿子的sum更新,sum[x]由xu[x]和splay子树上的儿子的sum更新。

这样我们就可以完整地用lct维护子树信息了。

需要注意的是,修改点权的时候一定要先make_root,不然会影响到祖先的sum和xu,复杂度就不对了。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
int n,m,id;
const int N =200005;
typedef unsigned long long ll;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch<='9'&&ch>='0')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x;
}
struct la{int u,v;ll x;}w[3*N];
ll S;
int cnt;
#define ju(x) (ch[fa[x]][1]==x)
#define nrt(x) ((ch[fa[x]][1]==x)||(ch[fa[x]][0]==x))
int fa[N],ch[N][2];
ll val[N],sum[N],xu[N];
bool r[N];
#define lc (ch[x][0])
#define rc (ch[x][1])
void ud(int x){
sum[x]=sum[lc]^sum[rc]^val[x]^xu[x];
}
inline void rev(int x){swap(lc,rc),r[x]^=1;}
void psdn(int x){
if(r[x]){
if(lc)rev(lc);
if(rc)rev(rc);
r[x]=0;
}
}
void push(int x){
if(nrt(x))push(fa[x]);
psdn(x);
}
inline void rot(int x){
int f=fa[x],of=fa[f],dir=ju(x),nt=nrt(f);
if(ch[x][dir^1])fa[ch[x][dir^1]]=f;
ch[f][dir]=ch[x][dir^1];
fa[f]=x,ch[x][dir^1]=f;
fa[x]=of;
if(nt)ch[of][ch[of][1]==f]=x;
ud(f),ud(x);
}
inline void splay(int x){
push(x);
for(int f=fa[x];nrt(x);rot(x),f=fa[x])
if(nrt(f))if(ju(x)^ju(f))rot(x);else rot(f);
}
inline void access(int x){
for(int y=0;x;x=fa[y=x]){
splay(x);
xu[x]^=sum[y];
xu[x]^=sum[ch[x][1]];
ch[x][1]=y;
ud(x);
//update!
}
}
inline void make_root(int x){
access(x),splay(x),rev(x);
}
inline void cut(int x,int y){
make_root(x),access(y),splay(x);
ch[x][1]=fa[y]=0;ud(x);
}
inline void link(int x,int y){
make_root(y),splay(y),make_root(x),splay(x),fa[x]=y;xu[y]^=sum[x];
}
inline void change(int x,ll v){
make_root(x);splay(x);val[x]^=v;
ud(x);
}
int main(){
srand(time(0));
id=read(),n=read(),m=read();
int u,v,op,x,y;
rep(i,2,n)scanf("%d%d",&u,&v),link(u,v);
while(m--){
op=read(),u=read();
if(op==1){
v=read(),x=read(),y=read();
cut(u,v),link(x,y);
}
else if(op==2){
v=read();
w[++cnt]=(la){u,v,(ll)1ll*rand()*rand()};
change(u,w[cnt].x),change(v,w[cnt].x);
S^=w[cnt].x;
}
else if(op==3){
x=w[u].u,y=w[u].v;
change(x,w[u].x),change(y,w[u].x);
S^=w[u].x;
}
else{
v=read();
make_root(u),access(v);
splay(u);
if(S==sum[v])puts("YES");
else puts("NO");
}
}
return 0;
}

【LCT维护子树信息】uoj207 共价大爷游长沙的更多相关文章

  1. uoj207 共价大爷游长沙 子树信息 LCT + 随机化 + 路径覆盖

    题目传送门 http://uoj.ac/problem/207 题解 如果是一棵静态的树,有一个非常容易想到的算法:统计一下目前的每一个条边被几条路径经过,如果 \(x\) 到 \(y\) 的边的这个 ...

  2. [UOJ207]共价大爷游长沙

    UOJ sol 这题真是太神啦! 对于S集合中的每个点对,给他们随机附上一个相同权值. 两个点在边(x,y)的两侧当且仅当一个点在x的子树中,另一个点不在x的子树中(假设x是y的儿子) 维护一下子树点 ...

  3. uoj207共价大爷游长沙

    话说我可能还没有调出魔法森林呢...说好的lct第一题呢... 又是一个随机化的方法,毕竟又是判定性的问题 上次是判断无向图联通 这次是判断一些路径是否经过一条定边 若把路径上的边全部异或上一个路径的 ...

  4. 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息

    题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...

  5. 共价大爷游长沙 lct 维护子树信息

    这个题目的关键就是判断 大爷所有可能会走的路 会不会经过询问的边. 某一条路径经过其中的一条边, 那么2个端点是在这条边的2测的. 现在我们要判断所有的路径是不是都经过 u -> v 我们以u为 ...

  6. UOJ #207. 共价大爷游长沙 [lct 异或]

    #207. 共价大爷游长沙 题意:一棵树,支持加边删边,加入点对,删除点对,询问所有点对是否经过一条边 一开始一直想在边权上做文章,或者从连通分量角度考虑,比较接近正解了,但是没想到给点对分配权值所以 ...

  7. 【UOJ207】共价大爷游长沙(Link-Cut Tree,随机化)

    [UOJ207]共价大爷游长沙(Link-Cut Tree,随机化) 题面 UOJ 题解 这题太神了 \(\%\%\%myy\) 看到动态的维护边很容易的想到了\(LCT\) 然后能否堵住一条路 我们 ...

  8. LCT维护子树信息

    有些题目,在要求支持link-cut之外,还会在线询问某个子树的信息.LCT可以通过维护虚边信息完成这个操作. 对于LCT上每个节点,维护两个两sz和si,后者维护该点所有虚儿子的信息,前者维护该点的 ...

  9. 「UOJ207」共价大爷游长沙

    「UOJ207」共价大爷游长沙 解题思路 : 快速判断两个集合是否完全相等可以随机点权 \(\text{xor}\) 的思路可以用到这道题上面,给每一条路径随机一个点权,维护出经过每一条边的点权的 \ ...

随机推荐

  1. exception 打印出异常栈踪迹

    Java异常抛出使用e.printStackTrace(),打印出抛出的异常栈踪迹, 如果你在catch中继续抛出这个异常,那么e.printStackTrace()也能跟踪到抛出异常的地方, 使用t ...

  2. iview+vue 使用中遇到的问题(表格、select、radio)

    1.iview+vue中,对表头的动态设置: iview表头若是需要动态设置,可以有两个方法,第一种: children: [ { title: '2017年', align: 'center', k ...

  3. 用shell脚本实现MongoDB数据库自动备份

    一.创建MongoDB备份目录 用来存放数据 mkdir -p /data/mongodb_bak/mongodb_bak_now mkdir -p /data/mongodb_bak/mongodb ...

  4. anaconda 安装2个python环境 亲测

    本机环境: anaconda3,pyhon3.7.4 配置第2个python环境,安装python3.6 > conda create --name tensorflow python=3.6 ...

  5. luoguP2680 运输计划 题解(二分答案+树上差分)

    P2680 运输计划  题目 这道题如果是看的我的树上差分来的,那么肯定一看题目就可以想到树上差分. 至于这是怎么想到的,一步一步来: 1.n有300000,不可能暴力枚举每一条边 2.因为我们要使运 ...

  6. 2019-4-8 zookeeper学习笔记

    zookeeper学习 ZooKeeper集合中的节点 让我们分析在ZooKeeper集合中拥有不同数量的节点的效果. 如果我们有单个节点,则当该节点故障时,ZooKeeper集合将故障.它有助于“单 ...

  7. vue - blog开发学习5

    基本功能和后台联调 1.首页的所有博客 因为是前后台都是本地开发,所以前端vue需要设置proxy:修改/config/index.js中的这个proxyTable proxyTable: { '/a ...

  8. 前端工程师的新选择WebApp

    作为新一代移动端应用分发入口,小程序的趋势明朗化,竞争也在急剧激烈化.战线从手机 QQ.QQ 浏览器.支付宝.手机淘宝,华为,小米等九家手机厂商推出“快应用”,再拉到了谷歌的 Instant App ...

  9. 中州韵输入法(rime)导入搜狗词库

    rime是一个非常优秀的输入法,linux平台下的反应速度远超搜狗,也没有隐私风险.2012年开始接触它,到后来抛弃了它,因为rime自带的词库真的太弱了,也懒得折腾.最近发现一个词库转换软件叫ime ...

  10. 【Java 其他】Java opencv配置及测试

    毕竟研究生做cv,所以这里还是测试一下java上使用opencv,参考 这里 import org.opencv.core.Core; import org.opencv.core.CvType; i ...