题目链接

题目描述

火车司机出秦川,跳蚤国王下江南,共价大爷游长沙。每个周末,勤劳的共价大爷都会开车游历长沙市。

长沙市的交通线路可以抽象成为一个 \(n\) 个点 \(n−1\) 条边的无向图,点编号为 \(1\) 到 \(n\),任意两点间均存在恰好一条路径,显然两个点之间最多也只会有一条边相连。有一个包含一些点对 \((x,y)\) 的可重集合\(S\),共价大爷的旅行路线是这样确定的:每次他会选择 \(S\) 中的某一对点 \((x,y)\),并从 \(x\) 出发沿着唯一路径到达 \(y\)。

小L是共价大爷的脑残粉,为了见到共价大爷的尊容,小L决定守在这张图的某条边上等待共价大爷的到来。为了保证一定能见到他,显然小L必须选择共价大爷一定会经过的边——也就是所有共价大爷可能选择的路径都经过的边。

现在小L想知道,如果他守在某一条边,是否一定能见到共价大爷。

然而长沙市总是不断的施工,也就是说,可能某个时刻某条边会断开,同时这个时刻一定也有某条新边会出现,且任意时刻图都满足任意两点间均存在恰好一条路径的条件。注意断开的边有可能和加入的新边连接着相同的两个端点。共价大爷的兴趣也会不断变化,所以S也会不断加入新点对或者删除原有的点对。当然,小L也有可能在任何时候向你提出守在某一条边是否一定能见到共价大爷的问题。你能回答小L的所有问题吗?

Sol

动态加删边用 \(LCT\)

考虑如何处理路径交。

一种方法是直接对链做一次覆盖。交必须满足被覆盖的次数为当前总的 \(S\) 集合大小

但是这种做法当我们删掉一条链上的边的时候 , 它必须要一个个把贡献去掉并且重新覆盖 , 显然是不行的。

我们要支持能够快速删除与当前边相关的所有路径覆盖操作的方法。

异或操作是支持快速撤销的 , 只需要再次异或一次就行了。

我们每次加入一条路径的时候给他随机一个权值 , 然后用这个权值去覆盖。

删除一条边时 , 我们能够直接知道这条边上的权值的异或和 , 用这个值重新覆盖一次新的路径即可,稍微画一下图就知道这个做法是对的了。这样做就要用 \(LCT\) 维护边权,不是那么好写。

另一种做法。

当我们询问一条边\((u,v)\)的时候 , 如果满足条件 , 必定是所有路径的一端在以 \(v\) 为根 \(u\) 的子树里 , 另一端在以 \(u\) 为根 \(v\) 的子树里 , 我们只需要判断一边就可以了。

于是还是给每一条路径随机一个权值 ,然后修改端点的权值。

于是只需要查询以\(u\)为根 \(v\) 的子树和是否和全局的一半一致即可。

code:

#include<bits/stdc++.h>
using namespace std;
template<class T>inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}
const int N=1e5+10;
int ID;
#define ls son[0]
#define rs son[1]
#define get_son(a) (a->fa->rs==a)
#define IS(a) ((a)&&((!(a->fa))||(a->fa->ls!=a&&a->fa->rs!=a)))
#define get_S(a) (a? a->S:0)
const int INF=1e9;
#define __ NULL
typedef long long ll;
struct node{
node *son[2],*fa;int val,S;bool rev;
node(){ls=rs=fa=__,S=val=rev=0;}
}T[N];
node* st[N];int top=0;
int n,m;
inline void update(node*p){if(!p) return;p->S=get_S(p->ls)^get_S(p->rs)^p->val;return;}
inline void push_down(node*p){
if(!p||!p->rev) return;
swap(p->ls,p->rs);
if(p->ls) p->ls->rev^=1;
if(p->rs) p->rs->rev^=1;
p->rev=0;
return;
}
inline void Push(node*p){top=0;
while(!IS(p)) st[++top]=p,p=p->fa;
push_down(p);while(top) push_down(st[top]),st[top--]=__;
}
inline void rotate(node*p){if(!p) return;
int k=get_son(p);node *q=p->fa,*gp=p->fa->fa;
q->son[k]=p->son[k^1];
if(p->son[k^1]) p->son[k^1]->fa=q;
if(!IS(q)) gp->son[get_son(q)]=p;
p->fa=gp;q->fa=p;p->son[k^1]=q;
return update(q);
}
inline void Splay(node*p){
if(!p) return;Push(p);
for(;!IS(p);rotate(p)) if(IS(p->fa)) continue;else (get_son(p->fa)==get_son(p)? rotate(p->fa):rotate(p));
return update(p);
}
int U[N*3],V[N*3],tot=0,val[N*3];
inline void access(node*p) {
node*pre=__;
for(;p;pre=p,p=p->fa) {Splay(p);p->val^=get_S(p->rs)^(get_S(pre));p->rs=pre;update(p);}
return;
}
inline void make_root(node*p){access(p);Splay(p);p->rev^=1;}
inline void split(node*p,node*q){make_root(p),access(q),Splay(q);};
inline void Link(node*p,node*q){split(p,q);p->fa=q;q->val^=p->S;update(q);}
inline void Cut(node*p,node*q){split(p,q);if(q->ls==p) p->fa=q->ls=__,update(q);}
int Sum=0;
int main()
{
srand(time(NULL));
init(ID);init(n),init(m);
int u,v;
for(int i=1;i<n;++i) {init(u),init(v);Link(&T[u],&T[v]);}
for(int i=1;i<=m;++i) {
int tp;
init(tp);
if(tp==1) {
int x,y;
init(x),init(y),init(u),init(v);
Cut(&T[x],&T[y]);
Link(&T[u],&T[v]);
}else if(tp==2) {
++tot;init(U[tot]),init(V[tot]);
val[tot]=(ll)rand()*rand()%INF;
Sum^=val[tot];
make_root(&T[U[tot]]);
T[U[tot]].val^=val[tot];T[U[tot]].S^=val[tot];
make_root(&T[V[tot]]);
T[V[tot]].val^=val[tot];T[V[tot]].S^=val[tot];
}else if(tp==3) {
int x;init(x);
Sum^=val[x];
make_root(&T[U[x]]);
T[U[x]].val^=val[x];T[U[x]].S^=val[x];
make_root(&T[V[x]]);
T[V[x]].val^=val[x];T[V[x]].S^=val[x];
}
else {
int x,y;init(x),init(y);
split(&T[x],&T[y]);
if(T[x].S==Sum) puts("YES");else puts("NO");
} }
}

【UOJ#207】共价大爷游长沙的更多相关文章

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

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

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

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

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

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

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

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

  5. UOJ #207. 共价大爷游长沙(LCT + 异或哈希)

    题目 维护一颗动态树,并维护一个点对集合 \(S\) . 动态查询一条边,是否被集合中所有点对构成的路径包含. \(n \le 100000, m \le 300000\) 题解 orz 前辈 毛爷爷 ...

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

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABHwAAAJZCAIAAABUW7XHAAAgAElEQVR4nOy93cstx5Xm2f9TXh2EOe

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

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

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

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

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

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

随机推荐

  1. RocketMQ 消费者

    本文分析 DefaultMQPushConsumer,异步发送消息,多线程消费的情形. DefaultMQPushConsumerImpl MQClientInstance 一个客户端进程只有一个 M ...

  2. TCP/IP 网络模型

    前言 互联网是怎么构成的,又是怎么运作的?什么是 TCP/IP 网络?为什么远隔万里的计算机可以互相通信?计算机网络作为 IT 行业的基石,是工程师永远绕不开的话题. 计算机网络的分层体系结构 计算机 ...

  3. 常用获取Android崩溃日志和IOS崩溃日志的几种方法

    一:前言 在日常测试app时,经常会遇到崩溃问题,测试快速抓取到崩溃日志可以有效方便开发进行定位,快速解决问题所在测试做到测试分析,定位是非常重要的,这也是判断一个测试能力指标的一大维度. 二:And ...

  4. python 使用 with open() as 读写文件

    读文件: 要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符: >>> f = open('E:\python\python\test.tx ...

  5. 【Linux开发】Ubuntu下几个软件的配置记录backup

    调用ubuntu命令行的方法:ctrl+alt+t gcc -o test test.c 开发工具包括eclipse,Qt等全部放入了/opt/路径下,java开发环境放在了/usr/local/jd ...

  6. 事件流程以及dom2级事件绑定

    事件流程分为三个阶段:捕获阶段.目标阶段.冒泡阶段. 捕获阶段:事件从最顶层元素开始执行,一层层往下,直到精确元素. 目标阶段:事件在精确元素上执行. 冒泡阶段:事件从精确元素开始执行,一层层往上,直 ...

  7. 前端为什么要学习 Selenium

    如果你正在阅读本文,那么可能希望从手动测试升级为自动化测试.你是对的,因为你需要学习 Selenium.我这样说是因为自动化测试已经风靡全球,而且业界正很缺少 Selenium 认证专家. 你可能还想 ...

  8. 出现( linker command failed with exit code 1)错误总结(http://blog.csdn.net/hengshujiyi/article/details/21182813)

    这种问题,通常出现在添加第三方库文件或者多人开发时. 这种问题一般是找不到文件而导致的链接错误. 我们可以从如下几个方面着手排查. 1.以如下错误为例,如果是多人开发,你同步完成后发现出现如下的错误. ...

  9. 关于Windows 10上MarkdownPad2无法预览的解决办法

    升级win10后,发现一直可以用的MarkdownPad2预览功能不可以用了.于是在网上搜索了一下,刚开始没有解决.不过现在可以了.现在把解决方案记录下来.Windows10上使用MarkdownPa ...

  10. 多线程 - 内存屏障和cpu缓存

    CPU性能优化 - 缓存 为了提高程序运行的性能,现代CPU在很多方面会对程序进行优化.CPU的处理速度是很快的,内存的速度次之,硬盘速度最慢.在cpu处理内存数据中,内存运行速度太慢,就会拖累cpu ...