【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息
题目描述
给出一棵树和一个点对集合S,多次改变这棵树的形态、在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边。
输入
输入的第一行包含一个整数 id,表示测试数据编号,如第一组数据的id=1,样例数据的 id 可以忽略。
输入的第二行包含两个整数 n,m,分别表示图中的点数,以及接下来会发生的事件数,事件的定义下文中会有描述。初始时 S 为空。
接下来 n−1 行,每行两个正整数 x,y,表示点 x 和点 y 之间有一条无向边。
接下来 m 行,每行描述一个事件,每行的第一个数 type 表示事件的类型。
若type=1,那么接下来有四个正整数x,y,u,v,表示先删除连接点x和点y的无向边,保证存在这样的无向边,然后加入一条连接点u和点v的无向边,保证操作后的图仍然满足题中所述条件。
若type=2,那么接下来有两个正整数 x,y,表示在 S 中加入点对 (x,y)。
若type=3,那么接下来有一个正整数 x,表示删除第 x 个加入 S 中的点对,即在第 x 个 type=2 的事件中加入 S 中的点对,保证这个点对存在且仍然在 S 中。
若 type=4,那么接下来有两个正整数 x,y,表示小L询问守在连接点 x 和点 y 的边上是否一定能见到共价大爷,保证存在这样的无向边且此时 S 不为空。
输出
对于每个小L的询问,输出“YES”或者“NO”(均不含引号)表示小L一定能或者不一定能见到共价大爷。
样例输入
0
5 7
1 2
1 3
2 4
1 5
2 1 5
1 1 5 2 5
4 2 5
2 1 4
4 2 5
3 1
4 2 4
题解
随机化+LCT维护子树信息
对与每个点对,随机一个权值,把这个权值异或到这两个点上。那么对于查询,如果 x 为树根时,y 子树中的所有点的权值的异或和等于所有点对的异或和,则视为所有点对间的路径都经过 x-y 。(别问我怎么想出来的。。。做过一道类似的题)
当权值范围足够大时可以近似视为正确。
由于树的形态是变化的,因此需要使用LCT维护子树信息,具体方法参见这里。
注意维护子树信息的LCT:link时需要makeroot(x),makeroot(y);修改时需要makeroot(x)而不是简单的splay(x);查询时需要先makeroot(x)。
时间复杂度 $O(LCT·n\log n)$
#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
int fa[N] , c[2][N] , rev[N] , w[N] , sum[N] , vx[N * 3] , vy[N * 3] , vw[N * 3] , tot;
inline void pushup(int x)
{
sum[x] = sum[c[0][x]] ^ sum[c[1][x]] ^ w[x];
}
inline void pushdown(int x)
{
if(rev[x])
{
int l = c[0][x] , r = c[1][x];
swap(c[0][l] , c[1][l]) , rev[l] ^= 1;
swap(c[0][r] , c[1][r]) , rev[r] ^= 1;
rev[x] = 0;
}
}
inline bool isroot(int x)
{
return c[0][fa[x]] != x && c[1][fa[x]] != x;
}
void update(int x)
{
if(!isroot(x)) update(fa[x]);
pushdown(x);
}
inline void rotate(int x)
{
int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
if(!isroot(y)) c[c[1][z] == y][z] = x;
fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
pushup(y) , pushup(x);
}
inline void splay(int x)
{
int y , z;
update(x);
while(!isroot(x))
{
y = fa[x] , z = fa[y];
if(!isroot(y))
{
if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
int t = 0;
while(x) splay(x) , w[x] ^= sum[c[1][x]] ^ sum[t] , c[1][x] = t , t = x , x = fa[x];
}
inline void makeroot(int x)
{
access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] ^= 1;
}
inline void link(int x , int y)
{
makeroot(x) , makeroot(y) , fa[x] = y , w[y] ^= sum[x] , pushup(y);
}
inline void cut(int x , int y)
{
makeroot(x) , access(y) , splay(y) , fa[x] = c[0][y] = 0 , pushup(y);
}
int main()
{
srand(20011011);
int n , m , i , opt , x , y , u , v , now = 0;
scanf("%*d%d%d" , &n , &m);
for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , link(x , y);
while(m -- )
{
scanf("%d%d" , &opt , &x);
if(opt == 1) scanf("%d%d%d" , &y , &u , &v) , cut(x , y) , link(u , v);
else if(opt == 2)
{
scanf("%d" , &y);
vx[++tot] = x , vy[tot] = y , vw[tot] = (rand() << 15) + rand() , now ^= vw[tot];
makeroot(x) , w[x] ^= vw[tot] , pushup(x);
makeroot(y) , w[y] ^= vw[tot] , pushup(y);
}
else if(opt == 3)
{
now ^= vw[x];
makeroot(vx[x]) , w[vx[x]] ^= vw[x] , pushup(vx[x]);
makeroot(vy[x]) , w[vy[x]] ^= vw[x] , pushup(vy[x]);
}
else scanf("%d" , &y) , makeroot(x) , access(y) , splay(y) , puts(sum[x] == now ? "YES" : "NO");
}
return 0;
}
【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息的更多相关文章
- UOJ #207. 共价大爷游长沙(LCT + 异或哈希)
题目 维护一颗动态树,并维护一个点对集合 \(S\) . 动态查询一条边,是否被集合中所有点对构成的路径包含. \(n \le 100000, m \le 300000\) 题解 orz 前辈 毛爷爷 ...
- UOJ #207. 共价大爷游长沙 [lct 异或]
#207. 共价大爷游长沙 题意:一棵树,支持加边删边,加入点对,删除点对,询问所有点对是否经过一条边 一开始一直想在边权上做文章,或者从连通分量角度考虑,比较接近正解了,但是没想到给点对分配权值所以 ...
- UOJ #207. 共价大爷游长沙
#207. 共价大爷游长沙 链接:http://uoj.ac/problem/207 题意:给一棵树,要求支持加边.删边.询问一条边是否被所有路径覆盖.同时路径端点集合有加入与删除操作. 想法: 考虑 ...
- 【刷题】UOJ #207 共价大爷游长沙
火车司机出秦川,跳蚤国王下江南,共价大爷游长沙.每个周末,勤劳的共价大爷都会开车游历长沙市. 长沙市的交通线路可以抽象成为一个 \(n\) 个点 \(n−1\) 条边的无向图,点编号为 \(1\) 到 ...
- UOJ#207. 共价大爷游长沙 LCT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ207.html 题解 第一次听说 LCT 还可以维护子树信息. 首先对于每一条路径 rand 一个值,分别 ...
- [UOJ#207. 共价大爷游长沙]——LCT&随机化
题目大意: 传送门 给一颗动态树,给出一些路径并动态修改,每次询问一条边是否被所有路径覆盖. 题解: 先%一发myy. 开始感觉不是很可做的样子,发现子树信息无论维护什么都不太对…… 然后打开题目标签 ...
- 数据结构(动态树):UOJ 207 共价大爷游长沙
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABHwAAAJZCAIAAABUW7XHAAAgAElEQVR4nOy93cstx5Xm2f9TXh2EOe
- LCT维护子树信息
有些题目,在要求支持link-cut之外,还会在线询问某个子树的信息.LCT可以通过维护虚边信息完成这个操作. 对于LCT上每个节点,维护两个两sz和si,后者维护该点所有虚儿子的信息,前者维护该点的 ...
- 【UOJ#207】共价大爷游长沙
题目链接 题目描述 火车司机出秦川,跳蚤国王下江南,共价大爷游长沙.每个周末,勤劳的共价大爷都会开车游历长沙市. 长沙市的交通线路可以抽象成为一个 \(n\) 个点 \(n−1\) 条边的无向图,点编 ...
随机推荐
- DSP6748学习笔记-190116
1. PSC是什么?电源和睡眠控制器.一个PSC模块由一个全局PSC和一组本地PSC组成,那么又是什么? PSCModuleControl(SOC_PSC_0_REGS, , PSC_POWERDOM ...
- 【JUC源码解析】CyclicBarrier
简介 CyclicBarrier,一个同步器,允许多个线程相互等待,直到达到一个公共屏障点. 概述 CyclicBarrier支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后 ...
- python-全栈开发-前方高能-内置函数
python_day_14 13. 前方高能-内置函数 ⼀. 本节主要内容: 1. 内置函数 什么是内置函数? 就是python给你提供的. 拿来直接⽤的函数, 比如print., input等等. ...
- 2019展望计划(Lamica 2019-Year Plan):
1,家人身体健康.2,好好上课,考试顺利,不要挂科.3,PETS3 9月份 杭州 一定要过.4,PETS3通过后,进军日语N3-N2.5,在杭州找一份合适的工作(底线6K).6,在杭州交到新朋友.7, ...
- Oracle数据库及图形化界面安装教程详解
百度云盘oracle数据库及图形化界面安装包 链接: https://pan.baidu.com/s/1DHfui-D2n1R6_ND3wDziQw 密码: f934 首先在电脑D盘(或者其他不是C盘 ...
- fetch上传文件报错的问题(multipart: NextPart: EOF)
技术栈 后台: gin(golang) 前端: react+antd+dva 问题 前端这边使用fetch发送http请求的时候,后端解析formData报错: multipart: NextPart ...
- 3星|李开复《AI·未来》:中国创业公司有独特优势,人工智能可能会加剧社会的不平等与不稳定
主要内容:作者对自己一些经历的回顾,对中美两国人工智能行业的回顾与展望. 作者认为中国的创业公司比美国节奏更快工作更拼命,深圳在硬件创新上远远领先于美国,中国创业公司们走出了一条跟美国不同的路. 作者 ...
- 账号被锁无法ssh登陆
Account locked due to failed logins 方法一: 使用root用户登陆后执行: pam_tally2 --user=username --reset 方法二: user ...
- 关于XSS的一些知识点
安全套接层(SSL)无助于减少XSS攻击.当Web浏览器使用SSL的时候,在网络中传送的数据是经过加密的,但是因为XSS攻击是在客户机器上发生的,所以数据已经被解密了,这时,攻击者仍然能够利用XSS安 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第八周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第八周学习总结 教材学习内容总结 本周内容主要为书第十二章内容: 堆(附加属性的二叉树) 完全二叉树 (最小堆)对于 ...