题目链接

题目描述

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

长沙市的交通线路可以抽象成为一个 \(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. hdu6599 I Love Palindrome String

    由样例可知,题目中求的回文串数量,其实是本质不同的回文串数量,这个可以直接用回文树来做. 考虑前半段是回文串这个限制,这个东西回文树不好做,可以再套一个马拉车,然后记录一下插入到回文树的节点中最后一个 ...

  2. 设计模式(4): 给组件实现单独的store

    概述 最近最近做项目的时候总会思考一些大的应用设计模式相关的问题,我把自己的思考记录下来,供以后开发时参考,相信对其他人也有用. 组件自身的store 我们在开发组件的时候,时常都有这种需求,就是希望 ...

  3. C++ com 组件 事件 备忘

    [ object, uuid(AECE8D0C-F902--A374-ED3A0EBB6B49), dual, nonextensible, pointer_default(unique) ] int ...

  4. 使用TestNG框架测试用例执行顺序问题

    既然是讨论执行顺序问题,那么用例肯定是批量执行的,批量执行的方法有mvn test.直接运行testng.xml文件,其中直接运行testng.xml文件的效果与pom文件中配置执行testng.xm ...

  5. dotnet core排序异常,本地测试和linux上结果不一致

    根据汉字排序,本地测试结构正常,发到docker之后,发现汉字升序降序和本地相反,检查代码后,没找到任何可能出现问题的点. 然后去翻文档:字符串比较操作 看到了这一句,会区分区域性 然后猜测应该是do ...

  6. 精读《Optional chaining》

    1. 引言 备受开发者喜爱的特性 Optional chaining 在 2019.6.5 进入了 stage2,让我们详细读一下草案,了解一下这个特性的用法以及讨论要点. 借着这次精读草案,让我们了 ...

  7. index.html(xpath素材)

    <bookstore> <title>新华书店</title> <book href="http://www.langlang2017.com/&q ...

  8. base64 换表 解密脚本

    做逆向经常遇到换表的base64 有了py脚本 一切都好说: import base64 import string str1 = "x2dtJEOmyjacxDemx2eczT5cVS9f ...

  9. MyBatis二级缓存的笔记及记录

    一.什么是二级缓存: 由于一级缓存是一次性的.临时的:每个会话都会创建一个新的:多个会话之间是不能共享的: 二级缓存用于解决一级缓存的不足:每一个“namespace”都会对应一个二级缓存:执行查询的 ...

  10. [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)

    [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理) 题面 一个\(n \times n\)的格子,每个格子里可以填\([1,k]\)内的整数. ...