XJOI网上同步训练DAY2 T2
【问题描述】
火车司机出秦川跳蚤国王下江南共价大爷游长沙。每个周末勤劳的共价大爷都会开车游历长沙市。
长沙市的交通线路可以抽象成为一个 个点 条边的无向图点编号为 到 任意两点间均存在恰好一条路径显然两个点之间最多也只会有一条边相连。有一个包含一些点对 的可重集合 共价大爷的旅行路线是这样确定的每次他会选择 中的某一对点 并从 出发沿着唯一路径到达 。
小L是共价大爷的脑残粉为了见到共价大爷的尊容小L决定守在这张图的某条边上等待共价大爷的到来。为了保证一定能见到他显然小L必须选择共价大爷一定会经过的边——也就是所有共价大爷可能选择的路径都经过的边。
现在小L想知道如果他守在某一条边是否一定能见到共价大爷。
然而长沙市总是不断的施工也就是说可能某个时刻某条边会断开同时这个时刻一定也有某条新边会出现且任意时刻图都满足任意两点间均存在恰好一条路径的条件。注意断开的边有可能和加入的新边连接着相同的两个端点。共价大爷的兴趣也会不断变化所以也会不断加入新点对或者删除原有的点对。当然小L也有可能在任何时候向你提出守在某一条边是否一定能见到共价大爷的问题。你能回答小L的所有问题吗
【输入格式】
从文件travel.in 中读入数据。
输入的第一行包含一个整数 表示测试数据编号如第一组数据的 样例数据的 可以忽略。
输入的第二行包含两个整数 分别表示图中的点数以及接下来会发生的事件数事件的定义下文中会有描述。初始时 为空。
接下来 行每行两个正整数 表示点 点 之间有一条无向边。
接下来 行每行描述一个事件每行的第一个数 表示事件的类型。
若 那么接下来有四个正整数 表示先删除连接点 点 的无向边保证存在这样的无向边然后加入一条连接点 点 的无向边保证操作后的图仍然满足题中所述条件。
若 那么接下来有两个正整数 表示在 中加入点对 。
若 那么接下来有一个正整数 表示删除第 个加入 中的点对即在第 个 的事件中加入 中的点对保证这个点对存在且仍然在 中。
若 那么接下来有两个正整数 表示小L询问守在连接点 点 的边上是否一定能见到共价大爷保证存在这样的无向边且此时 不为空。
【输出格式】
输出到travel.out中。
对于每个小L的询问输出“YES”或者“NO”均不含引号表示小L一定能或者不一定能见到共价大爷。
【样例输入1】
0
5 7
1 2
1 3
2 4
1 5
2 1 5
1 1 5 2 5
4 2 5
2 1 4
4 2 5
3 1
4 2 4
【样例输出1】
YES
NO
YES
【样例说明1】
最开始将点对 加入到 中此时点1和点5之间的路径是 。
接着将连接点1和点5的边断开加入连接点2和点5的边我们发现图仍然满足题中所述条件且点1和点5之间的路径是 经过点了2和点5之间的边因此第一个询问答案是YES。
接着将点对 加入到 中点1和点4之间的路径是 没有经过点2和点5之间的边因此第二个询问答案是NO。
接着我们删除了第一个加入到 中的点对也就是点对 此时 中唯一的点对就是 经过了点2和点4之间的边因此最后一个询问答案是YES。
【样例输入输出2】
见下发的travel / travel1.in与travel / travel1.ans。
【样例输入输出3】
见下发的travel / travel2.in与travel / travel2.ans这组数据中 。
【数据规模和约定】
数据点 |
的规模 |
的规模 |
= |
备注 |
1 |
1,2,3,4 |
|
||
2 |
2,4 |
|
||
3 |
2,4 |
|
||
4 |
2,3,4 |
|
||
5 |
2,3,4 |
|
||
6 |
1,2,3,4 |
任意时刻| |
||
7 |
1,2,3,4 |
任意时刻| |
||
8 |
1,2,3,4 |
|
||
9 |
1,2,3,4 |
|
||
10 |
1,2,3,4 |
|
对于所有数据 。
思路:本来想把边转换成点来做的,但是YY了一下发现,当把边拆掉的时候就不能维护信息了,题解的做法很玄妙:把每个路径的两个端点都异或上同一个随机值,然后询问的时候询问x子树和y子树内异或和是不是都等于ans,ans为每条边的随机值异或和。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int ch[500005][2],rev[500005],sum[500005],o[500005]; 7 int fa[500005]; 8 int c[500005][3],st[500005],ans; 9 int n,m,tot; 10 int read(){ 11 int t=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 14 return t*f; 15 } 16 bool isroot(int x){ 17 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; 18 } 19 void pushdown(int x){ 20 int l=ch[x][0],r=ch[x][1]; 21 if (rev[x]){ 22 rev[x]^=1; 23 rev[l]^=1;rev[r]^=1; 24 std::swap(ch[x][0],ch[x][1]); 25 } 26 } 27 void updata(int x){ 28 int l=ch[x][0],r=ch[x][1]; 29 sum[x]=o[x]^sum[l]^sum[r]; 30 } 31 void rotate(int x){ 32 int y=fa[x],f=ch[y][0]!=x; 33 if (ch[y][f]=ch[x][f^1]) fa[ch[y][f]]=y; 34 fa[x]=fa[y];if (!isroot(y)) ch[fa[y]][ch[fa[y]][0]!=y]=x; 35 updata(ch[fa[y]=x][f^1]=y); 36 } 37 void splay(int x){ 38 int top=0;st[++top]=x; 39 for (int i=x;!isroot(i);i=fa[i]) 40 st[++top]=fa[i]; 41 for (int i=top;i;i--) pushdown(st[i]); 42 while (!isroot(x)){ 43 int y=fa[x],z=fa[y]; 44 if (!isroot(y)){ 45 if (ch[y][0]==x^ch[z][0]==y) rotate(x); 46 else rotate(y); 47 } 48 rotate(x); 49 } 50 updata(x); 51 } 52 void access(int x){ 53 for (int t=0;x;t=x,x=fa[x]){ 54 splay(x); 55 o[x]^=sum[t]^sum[ch[x][1]]; 56 ch[x][1]=t; 57 updata(x); 58 } 59 } 60 void makeroot(int x){ 61 access(x);splay(x);rev[x]^=1; 62 } 63 void link(int x,int y){ 64 makeroot(x);makeroot(y);fa[x]=y;o[y]^=sum[x];updata(y); 65 } 66 void cut(int x,int y){ 67 makeroot(y);access(y); 68 splay(x); 69 fa[x]=0;o[y]^=sum[x];updata(y); 70 } 71 void add(int x,int y){ 72 access(x); 73 splay(x); 74 o[x]^=y; 75 updata(x); 76 } 77 int main(){ 78 int Id=read(); 79 n=read();m=read(); 80 srand(std::abs(n-m)*3+138); 81 for (int i=1;i<n;i++){ 82 int x=read(),y=read(); 83 link(x,y); 84 } 85 while (m--){ 86 int type=read(); 87 if (type==1){ 88 int x=read(),y=read(),u=read(),v=read(); 89 cut(x,y);link(u,v); 90 }else if (type==2){ 91 tot++; 92 c[tot][0]=read();c[tot][1]=read();int z=rand(); 93 while (!z) z=rand(); 94 c[tot][2]=z; 95 add(c[tot][0],z);add(c[tot][1],z);ans^=z; 96 }else if (type==3){ 97 int k=read(); 98 add(c[k][0],c[k][2]); 99 add(c[k][1],c[k][2]); 100 ans^=c[k][2]; 101 }else{ 102 int x=read(),y=read(); 103 makeroot(x);access(y); 104 if (o[x]==ans&&o[y]==ans) puts("YES"); 105 else puts("NO"); 106 } 107 } 108 }