题目

维护一颗动态树,并维护一个点对集合 \(S\) 。

动态查询一条边,是否被集合中所有点对构成的路径包含。

\(n \le 100000, m \le 300000\)

题解

orz 前辈 毛爷爷。

一个很有意思的 trick 。

如果一条边,被一条路径包含,那么两个端点分别存在与这条边对应的两个子树内。

我们就可以利用这个巧妙的性质来做了。

我们每次给两个端点异或上一个随机的权值,然后就可以每次查询这条边对应的任意一颗子树内所有点异或和 \(res\) ,如果 \(res\) 不等于前面所有操作的异或和,那么就是错的,否则就是正确的。

这利用了异或的自反性,如果两个端点都在子树中那么贡献就会抵消掉,所以就是不合法的。

可以证明这个正确率会非常的高。

至于维护子树信息,只需要 \(lct\) 多维护一个虚子树信息就行了,也就是对于 \(access,link,cut,pushup\) 多进行一些操作就行了。

总结

对于有些动态树路径的题,可以考虑只维护两个端点,不用维护整个路径上的信息。

然后可以利用异或的自反性,来保证集合中每个数出现并且仅出现一(奇数)次。

代码

具体实现就在代码里面了。

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__) using namespace std; typedef unsigned int ui; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
} void File() {
#ifdef zjp_shadow
freopen ("207.in", "r", stdin);
freopen ("207.out", "w", stdout);
#endif
} const int N = 1e5 + 1e3; #define ls(o) ch[o][0]
#define rs(o) ch[o][1] template<int Maxn>
struct Link_Cut_Tree { int ch[Maxn][2], fa[Maxn]; inline bool is_root(int o) {
return ls(fa[o]) != o && rs(fa[o]) != o;
} inline bool get(int o) {
return rs(fa[o]) == o;
} ui val[Maxn], sub[Maxn], isub[Maxn]; inline void push_up(int o) {
sub[o] = sub[ls(o)] ^ sub[rs(o)] ^ isub[o] ^ val[o];
} void rotate(int v) {
int u = fa[v], t = fa[u], d = get(v);
fa[ch[u][d] = ch[v][d ^ 1]] = u;
fa[v] = t; if (!is_root(u)) ch[t][rs(t) == u] = v;
fa[ch[v][d ^ 1] = u] = v;
push_up(u); push_up(v);
} bool rev[Maxn]; inline void Get_Rev(int o) {
rev[o] ^= 1; swap(ls(o), rs(o));
} inline void push_down(int o) {
if (rev[o])
Get_Rev(ls(o)), Get_Rev(rs(o)), rev[o] = false;
} void Push_All(int o) {
if (!is_root(o)) Push_All(fa[o]); push_down(o);
} inline void Splay(int o) {
Push_All(o);
for (; !is_root(o); rotate(o))
if (!is_root(fa[o])) rotate(get(o) != get(fa[o]) ? o : fa[o]);
} inline void Access(int o) {
for (int t = 0; o; o = fa[t = o])
Splay(o), isub[o] ^= sub[rs(o)], isub[o] ^= sub[rs(o) = t], push_up(o);
} inline void Make_Root(int o) {
Access(o); Splay(o); Get_Rev(o);
} inline void Split(int u, int v) {
Make_Root(u); Access(v); Splay(v);
} inline void Link(int u, int v) {
Split(u, v); fa[u] = v; isub[v] ^= sub[u]; push_up(v);
} inline void Cut(int u, int v) {
Split(u, v); ls(v) = fa[u] = 0; push_up(v);
} }; Link_Cut_Tree<N> T; inline void Update(int o, ui val) {
T.Access(o); T.Splay(o); T.val[o] ^= val; T.push_up(o);
} random_device Rand; pair<int, int> Up[N * 3]; ui Val[N * 3], len = 0; int main () { File(); read(); int n = read(), m = read(); For (i, 1, n - 1) T.Link(read(), read()); ui cur = 0;
For (i, 1, m) { int opt = read();
if (opt == 1) {
int x = read(), y = read(), u = read(), v = read();
T.Cut(x, y); T.Link(u, v);
}
if (opt == 2) {
int x = read(), y = read(); Val[++ len] = Rand();
cur ^= Val[len]; Update(x, Val[len]); Update(y, Val[len]);
Up[len] = make_pair(x, y);
}
if (opt == 3) {
int id = read(), x = Up[id].first, y = Up[id].second;
cur ^= Val[id]; Update(x, Val[id]); Update(y, Val[id]);
}
if (opt == 4) {
int x = read(), y = read();
T.Split(x, y);
puts(T.sub[x] == cur ? "YES" : "NO");
}
} return 0; }

UOJ #207. 共价大爷游长沙(LCT + 异或哈希)的更多相关文章

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

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

  2. [UOJ#207. 共价大爷游长沙]——LCT&随机化

    题目大意: 传送门 给一颗动态树,给出一些路径并动态修改,每次询问一条边是否被所有路径覆盖. 题解: 先%一发myy. 开始感觉不是很可做的样子,发现子树信息无论维护什么都不太对…… 然后打开题目标签 ...

  3. UOJ#207. 共价大爷游长沙 LCT

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ207.html 题解 第一次听说 LCT 还可以维护子树信息. 首先对于每一条路径 rand 一个值,分别 ...

  4. UOJ #207. 共价大爷游长沙

    #207. 共价大爷游长沙 链接:http://uoj.ac/problem/207 题意:给一棵树,要求支持加边.删边.询问一条边是否被所有路径覆盖.同时路径端点集合有加入与删除操作. 想法: 考虑 ...

  5. 【刷题】UOJ #207 共价大爷游长沙

    火车司机出秦川,跳蚤国王下江南,共价大爷游长沙.每个周末,勤劳的共价大爷都会开车游历长沙市. 长沙市的交通线路可以抽象成为一个 \(n\) 个点 \(n−1\) 条边的无向图,点编号为 \(1\) 到 ...

  6. 数据结构(动态树):UOJ 207 共价大爷游长沙

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABHwAAAJZCAIAAABUW7XHAAAgAElEQVR4nOy93cstx5Xm2f9TXh2EOe

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

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

  8. 【UOJ#207】共价大爷游长沙

    题目链接 题目描述 火车司机出秦川,跳蚤国王下江南,共价大爷游长沙.每个周末,勤劳的共价大爷都会开车游历长沙市. 长沙市的交通线路可以抽象成为一个 \(n\) 个点 \(n−1\) 条边的无向图,点编 ...

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

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

随机推荐

  1. pip3 升级失败的解决方法!亲测有效

    pip3 --default-timeout=10000 install -U pip 注意:由于防火长城的存在,会导致更新失败,如果你加上--default-timeout=10000  这个就ok ...

  2. 【kindle笔记】之 《黑客微百科》-2018-6-17

    前段时间复习六级的时候,从图书馆看到一本书,然后带回来了.今天开始读.今天是2018年6月17日. 严格来讲,一本不算kindle笔记的笔记,不过广义的啃豆笔记了解一下.哈哈. 首页说到的黑客理念是: ...

  3. JEECG 3.7 Memory Leak

    JEECG 3.7 版本常见问题贴 - JEECG官方网站-企业级JAVA快速开发平台 - Powered by Discuz!http://www.jeecg.org/forum.php?mod=v ...

  4. PHP之位运算符

    使用场景: 1) 判断奇数偶数 ; $i < ; $i++) { ){ echo $i.PHP_EOL; } } //输出所有奇数 2)快速修改状态 $status1 = ; $status2 ...

  5. python3 网页下拉框和悬浮框操作基础汇总

    #悬浮定位操作 from selenium.webdrier import ActionChains #浏览器实例化 #定位移动的位置赋给一个参数 ActionChains(浏览器).move_to_ ...

  6. [转帖]Linux 的静态库与动态库

    Linux下的静态库与动态库 2017年02月18日 09:17:13 LLZK_ 阅读数:10257 标签: linux动态库静态库区别使用 更多 个人分类: Linux学习笔记 所属专栏: Lin ...

  7. day 7-17 多表查询

    一. 准备表 #部门表 create table dep( id int, name varchar(20) ); #员工表 create table emp( id int primary key ...

  8. Flutter 中 JSON 解析

    本文介绍一下Flutter中如何进行json数据的解析.在移动端开发中,请求服务端返回json数据并解析是一个很常见的使用场景.Android原生开发中,有GsonFormat这样的神器,一键生成Ja ...

  9. Android——SMS接收发短信与运行权限

    好久没写了,最近学习Android的相关知识,包括UI组件与布局.Activity生命周期等,而这次要讲的是,Broadcast Receiver的相关知识,主要是接收发短信,SmsManager.S ...

  10. 在windows 7上安装TensorFlow

    TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习.目前被50个团队用于研究和生产许多Google商业产品,如语音识别.Gmail.Google 相册和搜索,其中许多产品曾使用 ...