[UOJ207]共价大爷游长沙(随机,动态树维护子树和)
2018-02-01 00:32
447 查看
Description
维护一个数据结构,要求对树支持以下操作:添加一条边,删除一条边。
在集合SS中加入点对(x,y)(x,y)
删除集合中的某个点对。
询问某条边是否被SS中所有点对间的路径经过。
Solution
myy的题,感觉好神啊,只会做50分。考虑询问的边 (x,y)(x,y) 被所有点对路径经过相当于以xx为根时,所有点对都恰有一个端点在以yy的子树中。
所以对每个点对随机一个权值,并让端点异或上这个权值。每次询问时查询以yy为根的子树异或和是否等于总异或和即可。
#include <bits/stdc++.h> using namespace std; const int maxn = 100005, maxm = 300005; int n, m, Id, S, x[maxm], y[maxm], z[maxm], cnt; int ch[maxn][2], vsum[maxn], sum[maxn], f[maxn], val[maxn], rev[maxn]; int Rand(int l,int r) { double dou=1.0*rand()/RAND_MAX; return dou*(r-l+1)+l; } #define isroot(x) (ch[f[x]][0] != x && ch[f[x]][1] != x) #define get(x) (ch[f[x]][1] == x) #define update(x) sum[x] = vsum[x] ^ val[x] ^ sum[ch[x][0]] ^ sum[ch[x][1]] inline void rotate(int x) { int fa = f[x], gfa = f[fa], k = get(x); if(!isroot(fa)) ch[gfa][get(fa)] = x; ch[fa][k] = ch[x][k ^ 1]; f[ch[x][k ^ 1]] = fa; ch[x][k ^ 1] = fa; f[fa] = x; f[x] = gfa; update(fa); update(x); } int stk[maxn], top; inline void pushdown(int x) { if(!x || !rev[x]) return ; if(ch[x][0]) rev[ch[x][0]] ^= 1; if(ch[x][1]) rev[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); rev[x] = 0; } inline void splay(int x) { stk[top = 1] = x; while(!isroot(x)) stk[++top] = x = f[x]; while(top) pushdown(stk[top--]); x = stk[1]; while(!isroot(x)) { int fa = f[x]; if(!isroot(fa)) get(fa) ^ get(x) ? rotate(x) : rotate(fa); rotate(x); } update(x); } inline void access(int x) { for(int y = 0; x; y = x, x = f[x]) { splay(x); vsum[x] ^= sum[ch[x][1]] ^ sum[y]; ch[x][1] = y; update(x); } } inline void make_root(int x) {access(x); splay(x); rev[x] ^= 1;} inline void link(int x, int y) {make_root(x); make_root(y); vsum[y] ^= sum[x]; f[x] = y;} inline void cut(int x, int y) {make_root(x); access(y); splay(y); f[x] = ch[y][0] = 0; update(x); update(y);} inline void insert(int u, int v, int w) { make_root(u); splay(u); val[u] ^= w; sum[u] ^= w; make_root(v); splay(v); val[v] ^= w; sum[v] ^= w; } inline bool query(int x, int y) { make_root(x); access(y); splay(y); return sum[x] == S; } int main() { freopen("visit.in", "r", stdin); freopen("visit.out", "w", stdout); scanf("%d%d%d", &Id, &n, &m); for(int u, v, i = 1; i < n; ++i) scanf("%d%d", &u, &v), link(u, v); for(int opt, u, v, w, i = 1; i <= m; ++i) { scanf("%d", &opt); if (opt == 1) { scanf("%d%d", &u, &v); cut(u, v); scanf("%d%d", &u, &v); link(u, v); }else if (opt == 2) { scanf("%d%d", &u, &v); w = Rand(1, 1000000000); S ^= w; insert(u, v, w); ++cnt; x[cnt] = u; y[cnt] = v; z[cnt] = w; }else if (opt == 3) { scanf("%d", &u); insert(x[u], y[u], z[u]); S ^= z[u]; }else if (opt == 4) { scanf("%d%d", &u, &v); if(query(u, v)) puts("YES"); else puts("NO"); } } return 0; }
相关文章推荐
- 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息
- [UOJ207]共价大爷游长沙
- [UOJ207]共价大爷游长沙
- UOJ #207. 共价大爷游长沙(不用维护子树的LCT)
- UOJ207 共价大爷游长沙
- UOJ 207 共价大爷游长沙
- UOJ#207:共价大爷游长沙(LCT维护子树信息)
- UOJ #207. 共价大爷游长沙
- UOJ #207. 共价大爷游长沙
- uoj#207. 共价大爷游长沙
- UOJ #207. 共价大爷游长沙 [lct 异或]
- uoj207共价大爷游长沙
- 【UOJ #207】共价大爷游长沙
- uoj#207 共价大爷游长沙
- [UOJ#207]共价大爷游长沙
- 【uoj207】 共价大爷游长沙
- 【UOJ207】共价大爷游长沙(Link-Cut Tree,随机化)
- 【UOJ207】共价大爷游长沙(Link-Cut Tree,随机化)
- UOJ207:共价大爷游长沙