[UOJ#207]共价大爷游长沙
题目大意
一颗会动的树。
有一个点对集合会变。
每次询问一条树边,问集合内所有点对之间的路径是否都经过该边。
维护虚边信息的LCT
终于无聊来补了这题
每个点对随机一个10^9内的权值
然后给两端点的点权分别异或给权值。
询问一条边是否被全部经过,就是询问每个点对是否都被这条边分开。
那么比如这条边是(u,v),断开后u的子树异或和应该要等于当前所有路径权值异或和。
就可以判了,出错率当然是很低啦。
#include<cstdio>
#include<algorithm>
#include<ctime>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10,maxm=300000+10,md=1000000000;
int ask[maxm][5],size[maxm*4],c[maxm],b[maxm];
int key[maxn],num[maxn],siz[maxn],father[maxn],tree[maxn][2],pp[maxn],sum[maxn],sta[maxn];
bool bz[maxn];
int h[maxn],go[maxn*2],next[maxn*2];
int i,j,k,u,v,l,t,n,m,tot,top,wdc,ans,id;
int random(int x){ll t=rand()%10000;t=t*10000+rand()%10000;t=t*10000+rand()%10000;return t%x;
}
int read(){int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
void add(int x,int y){go[++tot]=y;next[tot]=h[x];h[x]=tot;
}
void dfs(int x,int y){pp[x]=y;int t=h[x];while (t){if (go[t]!=y) dfs(go[t],x);t=next[t];}
}
int pd(int x){return tree[father[x]][1]==x;
}
void update(int x){siz[x]=siz[tree[x][0]]^siz[tree[x][1]]^key[x];num[x]=num[tree[x][0]]^num[tree[x][1]]^sum[x];
}
void rotate(int x){int y=father[x],z=pd(x);father[x]=father[y];if (father[y]) tree[father[y]][pd(y)]=x;tree[y][z]=tree[x][1-z];if (tree[x][1-z]) father[tree[x][1-z]]=y;tree[x][1-z]=y;father[y]=x;update(y);update(x);if (pp[y]) pp[x]=pp[y],pp[y]=0;
}
void clear(int x){if (bz[x]){if (tree[x][0]) bz[tree[x][0]]^=1;if (tree[x][1]) bz[tree[x][1]]^=1;swap(tree[x][0],tree[x][1]);bz[x]=0;}
}
void remove(int x,int y){top=0;while (x!=y){sta[++top]=x;x=father[x];}while (top){clear(sta[top]);top--;}
}
void splay(int x,int y){remove(x,y);while (father[x]!=y){if (father[father[x]]!=y) if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);rotate(x);}
}
int find_left(int x){if (!x) return 0;clear(x);if (!tree[x][0]) return x;else return find_left(tree[x][0]);
}
int getnum(int x){splay(x,0);return sum[x]^num[tree[x][1]]^siz[tree[x][1]]^key[x];
}
void real_empty(int x,int y){int t=getnum(x);splay(y,0);splay(x,y);tree[y][1]=0;father[x]=0;pp[x]=y;sum[y]^=t;update(y);
}
void empty_real(int x,int y){int t=getnum(x);splay(y,0);splay(x,0);tree[y][1]=x;father[x]=y;pp[x]=0;sum[y]^=t;update(y);
}
void access(int x){int y,z;splay(x,0);z=find_left(tree[x][1]);if (z){splay(z,x);real_empty(z,x);}while (pp[x]){y=pp[x];splay(y,0);z=find_left(tree[y][1]);if (z){splay(z,y);real_empty(z,y);}splay(x,0);z=find_left(x);splay(z,0);empty_real(z,y);splay(x,0);}
}
void makeroot(int x){access(x);splay(x,0);bz[x]^=1;
}
void cut(int x,int y){makeroot(x);access(x);int t=getnum(y);splay(x,0);sum[x]^=t;update(x);splay(y,0);pp[y]=0;
}
void link(int x,int y){makeroot(x);makeroot(y);int t=getnum(y);splay(x,0);sum[x]^=t;update(x);splay(y,0);pp[y]=x;
}
void insert(int p,int l,int r,int a,int b){if (l==r){size[p]+=b;return;}int mid=(l+r)/2;if (a<=mid) insert(p*2,l,mid,a,b);else insert(p*2+1,mid+1,r,a,b);size[p]=size[p*2]+size[p*2+1];
}
int kth(int p,int l,int r,int k){if (l==r) return l;int mid=(l+r)/2;if (k<=size[p*2]) return kth(p*2,l,mid,k);else return kth(p*2+1,mid+1,r,k-size[p*2]);
}
int main(){//freopen("data.in","r",stdin);freopen("data.out","w",stdout);srand(time(0));id=read();n=read();m=read();fo(i,1,n-1){j=read();k=read();add(j,k);add(k,j);}dfs(1,0);tot=0;fo(i,1,m){ask[i][0]=read();ask[i][1]=read();if (ask[i][0]!=3) ask[i][2]=read();if (ask[i][0]==1) ask[i][3]=read(),ask[i][4]=read();if (ask[i][0]==2) ask[i][3]=++tot,c[tot]=i;}fo(i,1,m){if (ask[i][0]==1){j=ask[i][1];k=ask[i][2];u=ask[i][3];v=ask[i][4];cut(j,k);link(u,v);}else if (ask[i][0]==2){insert(1,1,tot,ask[i][3],1);j=ask[i][1];k=ask[i][2];b[ask[i][3]]=random(md)+1;access(j);splay(j,0);key[j]^=b[ask[i][3]];update(j);access(k);splay(k,0);key[k]^=b[ask[i][3]];update(k);wdc^=b[ask[i][3]];}else if (ask[i][0]==3){//t=kth(1,1,tot,ask[i][1]);t=ask[i][1];insert(1,1,tot,t,-1);j=ask[c[t]][1];k=ask[c[t]][2];access(j);splay(j,0);key[j]^=b[ask[c[t]][3]];update(j);access(k);splay(k,0);key[k]^=b[ask[c[t]][3]];update(k);wdc^=b[ask[c[t]][3]];}else{j=ask[i][1];k=ask[i][2];cut(j,k);makeroot(j);ans=getnum(j);if (ans==wdc) printf("YES\n");else printf("NO\n");link(j,k);}}
}
[UOJ#207]共价大爷游长沙相关推荐
- 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息
题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...
- 【uoj207】 共价大爷游长沙
http://uoj.ac/problem/207 (题目链接) 题意 给出一棵无根树,4种操作:在路径集合中加入一条路径,在路径集合中删除一条路径,删一条边加一条边,查询一条边是否被集合中所有路径经 ...
- 【UOJ207】共价大爷游长沙【LCT】【异或】【随机化】
传送门 题意:维护一棵无权树和一个路径集合SSS,支持以下操作: 断边连边 在SSS加入中加入一条路径 删除SSS中的一条路径 询问是否SSS中的所有路径都经过了边(x,y)(x,y)(x,y) n≤ ...
- UOJ207 共价大爷游长沙
考虑到路径是有向的,不是很好维护. 如果路径无向的话,可以直接转化为链加和查询操作. 既然有向的话,不妨考虑一波hash. 对于一组询问x,y,可以把树划分为两颗子树. 合法显然需要满足 x子树的起点 ...
- 一句话题解(20170801~20170125)
8.1 bzoj 4720 noip2016 换教室 floyd预处理+期望(薛定谔的猫) bzoj 4318 OSU! 三次函数期望值 从一次.二次推得 8.2 bzoj 1076 状压+期望DP ...
- ZJOI2019Round#1
考的这么差二试基本不用去了 不想说什么了.就把这几天听课乱记的东西丢上来吧 这里是二试乱听课笔记ZJOI2019Round#2 ZJOI Round#1 Day1 M.<具体数学>选讲 罗 ...
- 跑出数字化升级“加速度”,腾讯云启产业基地“长沙模式”的探索
文 | 曾响铃 来源 | 科技向令说(xiangling0815) 当互联网与产业加速融合,数字经济成为发展新引擎. 在长沙,2019年,深耕岩土工程自动化监测领域的湖南湘银河传感科技有限公司,借助湘 ...
- 画论38 董其昌《画禅室随笔》
[中国历代画论目录] 目录 卷一 ◎论用笔 ◎评法书 ◎跋自书 ◎评古帖 卷二 ◎画诀 ◎画源 ◎题自画 ◎评旧画 卷三 ◎记事 ◎记游 ◎评诗 ◎评文 卷四 ◎杂言上 ◎杂言下 ◎楚中随笔 ◎禅悦 ...
- 书论66 董其昌《画禅室随笔》
目录 卷一 论用笔 评法书 评古帖 卷二 画诀 画源 题自画 评旧画 论画 卷三 记事 记游 评诗 评文 卷四 杂言上 杂言下 楚中随笔 禅悦 卷一 论用笔 米海岳书,无垂不缩,无往不收.此八字真言, ...
最新文章
- Java分布式 RPC 框架性能大比拼,Dubbo最差?
- 9 岁自学编程、24 岁身价涨至数百万美元,与微软一较高低的大佬多厉害?
- SQL Server之其他函数——空值处理
- Ajax -get 请求
- 坐标偏差大_控制点的坐标复核(二)
- .ini文件中的PHP 5.6 error_reporting设置不起作用
- 记一些暂未找到解决方案的问题 -- 持续更新
- git 回退上一个版本_Git小白使用教程:详细、显现、真正手把手教!
- go 二进制程序守护_图解 Go 程序是怎样跑起来的
- 盒子模型阴影设置,爱奇艺阴影配置
- [剑指offer][JAVA]面试题第[30]题[包含min函数的栈][双栈辅助栈][单栈]
- 【CodeForces - 298C】Parity Game (思维,有坑)
- DataGrid的动态绑定问题(二)
- 2.shell 程序设计(1)
- 揭示Win32 API拦截细节/API hooking revealed (2)
- visio2010安装
- mysql读mdf_mdf文件导入mysql,mysql怎么导入mdf文件 | 帮助信息-动天数据
- matlab版本低能用吗,MATLAB高版本打开低版本
- 如何精细化APP运营
- 大数据是什么意思?就业前景如何?