http://uoj.ac/problem/207 (题目链接)

题意

  给出一棵无根树,4种操作:在路径集合中加入一条路径,在路径集合中删除一条路径,删一条边加一条边,查询一条边是否被集合中所有路径经过。

Solution

  将路径端点同时异或上一个值,那么如果一条路径被经过,那么它的子树中点的异或和一定等于所有路径的异或和。

  考虑如何用LCT维护这种可加减的子树信息。

  对于询问,我们将询问的点access一下,那么它的所有虚儿子就是它在真实的树中的所有儿子了。

  对于会使轻重边切换的操作:access,link,cut。注意同时更新虚儿子信息。

细节

  link的时候,两端点都要makeroot,否则作为父亲的一点无法更新祖先的信息。

代码

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=300010;
int S,n,m,id,tot,fa[maxn]; struct edge {int u,v,w;}e[maxn];
struct node {
int son[2],val,sum,rev; //val=x+虚儿子;sum=val+实儿子
int& operator [] (int x) {return son[x];}
}tr[maxn]; void reverse(int x) {
swap(tr[x][0],tr[x][1]);tr[x].rev^=1;
}
void pushdown(int x) {
if (tr[fa[x]][0]==x || tr[fa[x]][1]==x) pushdown(fa[x]);
if (tr[x].rev) {
if (tr[x][0]) reverse(tr[x][0]);
if (tr[x][1]) reverse(tr[x][1]);
tr[x].rev^=1;
}
}
void pushup(int x) {
tr[x].sum=tr[tr[x][0]].sum^tr[tr[x][1]].sum^tr[x].val;
}
void rotate(int x) {
int y=fa[x],z=fa[y],l,r;
l=tr[y][1]==x;r=l^1;
if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x;
fa[tr[x][r]]=y;fa[x]=z;fa[y]=x;
tr[y][l]=tr[x][r];tr[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x) {
pushdown(x);
while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) {
int y=fa[x],z=fa[y];
if (tr[z][0]==y || tr[z][1]==y) {
if ((tr[z][0]==y) ^ (tr[y][0]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {
for (int y=0;x;y=x,x=fa[x]) {
splay(x);tr[x].val^=tr[tr[x][1]].sum;
tr[x].val^=tr[tr[x][1]=y].sum;
pushup(x);
}
}
void makeroot(int x) {
access(x);splay(x);reverse(x);
}
void link(int x,int y) {
makeroot(x);makeroot(y); //一定要makeroot(y),否则无法更新y所在的splay上祖先的信息
fa[x]=y;tr[y].val^=tr[x].sum;
pushup(y);
}
void cut(int x,int y) {
makeroot(x);access(y);splay(y);
fa[x]=tr[y][0]=0;pushup(y);
}
void modify(int x,int val) {
access(x);splay(x);
tr[x].val^=val;tr[x].sum^=val;
}
bool query(int x,int y) {
makeroot(x);access(y); //access以后,y在实树上的儿子全为它的虚儿子
return tr[y].val==S ? 1 : 0;
} int main() {
scanf("%d%d%d",&id,&n,&m);
for (int x,y,i=1;i<n;i++) {
scanf("%d%d",&x,&y);
link(x,y);
}
for (int op,x,y,z,i=1;i<=m;i++) {
scanf("%d",&op);
if (op==1) {
scanf("%d%d",&x,&y);cut(x,y);
scanf("%d%d",&x,&y);link(x,y);
}
if (op==2) {
scanf("%d%d",&x,&y);
e[++tot]=(edge){x,y,z=rand()};
modify(x,z),modify(y,z);S^=z;
}
if (op==3) {
scanf("%d",&x);S^=e[x].w;
modify(e[x].u,e[x].w);modify(e[x].v,e[x].w);
}
if (op==4) {
scanf("%d%d",&x,&y);
puts(query(x,y) ? "YES" : "NO");
}
}
return 0;
}

  

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

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

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

  2. uoj207共价大爷游长沙

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

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

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

  4. 【LCT维护子树信息】uoj207 共价大爷游长沙

    这道题思路方面就不多讲了,主要是通过这题学一下lct维护子树信息. lct某节点u的子树信息由其重链的一棵splay上信息和若干轻儿子子树信息合并而成. splay是有子树结构的,可以在rotate, ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 面试2——java基础3

    21.Http请求的get和post的区别? get:从 指定的资源请求数据.请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的 post:向指定的资源提交要被处理的数据.请注意, ...

  2. JDK的一个关于stack的小bug

    在一个项目中,使用了一个java.util.Stack,总所周知,栈是先入后出的,那么遍历其中元素的时候,也应该按照这个顺序遍历才对,但是实际情况确不是,以下是测试代码. Stack stack = ...

  3. HTTP Error 500.22 - Internal Server Error 错误解决方案

    1. 首先进入IIS ,配置IIS 应用程序池的.Net Framework版本 2. 点击左侧应用程序池,再单机右侧设置,选择版本 3. 设置为经典模式 如若遇到以下错误: 解决方案:删除confi ...

  4. width,height为多少px时,A4纸打印时刚好一页?

    计算方式一般的分辨率为XX像素/英寸,其中一英寸为25.4毫米.所以一毫米的像素数就为XX/25.4.现在的工作就是求XX的值了,把XX的值求出来以后,直接用XX/25.4 * 210就得到A4纸的像 ...

  5. Ubuntu apt-get提示被锁住

    执行 apt-get 时提示资源被锁住 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavai ...

  6. Linux内核分析 第七周 可执行程序的装载

    张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核分析 第七 ...

  7. 《Linux内核设计与实现》 第五周 读书笔记(第十八章)

    第18章 调试 20135307张嘉琪 18.1 准备开始 18.2 内核中的bug 内核中的bug多种多样,它们的产生可以有无数的原因,同时它们的表象也变化多端,从明白无误的错误代码(比如,没有把正 ...

  8. 使用代理创建连接池 proxyPool

    配置文件properties url=jdbc:mysql://127.0.0.1:3306/mine?characterEncoding=UTF-8 user=root password=1234 ...

  9. Github知识小结

    软件:计算机运行所需要的各种程序和数据的总成,包括操作系统,汇编语言,编译,程序,数据库,文字编辑和维护使用手册等. 软件的特性:(1)软件产品的主要生产是脑力劳动,还没有摆脱手工开发方式(2)软件是 ...

  10. 关于RESTful 的概念

    1.REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露.URI 的设计只要负责把资源通过合理方式暴露出来就可以了.对资源的操作与它无关,操作是通过 HTTP动词来体现,所以RES ...