BZOJ 3123: [Sdoi2013]森林
2017-01-10 10:51
295 查看
3123: [Sdoi2013]森林
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2745 Solved: 808
[Submit][Status][Discuss]
Description
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> inline char nextC(void) { static const int siz = 1024; static char buf[siz]; static char *hd = buf + siz; static char *tl = buf + siz; if (hd == tl) fread(hd = buf, 1, siz, stdin); return *hd++; } inline int nextI(void) { register int ret = 0; register int neg = false; register int bit = nextC(); for (; bit < 48; bit = nextC()) if (bit == '-')neg ^= true; for (; bit > 47; bit = nextC()) ret = ret * 10 + bit - 48; return neg ? -ret : ret; } inline bool nextO(void) { register char c = nextC(); while (c != 'Q' && c != 'L') c = nextC(); return c == 'Q'; } const int siz = 1000005; int n, m, q; int val[siz]; int map[siz], tot; inline void initMap(void) { tot = 0; for (int i = 1; i <= n; ++i) map[++tot] = val[i]; // printf("tot = %d\n", tot); // // for (int i = 1; i < tot; ++i) // printf("%d ", map[i]); // puts(""); using namespace std; sort(map + 1, map + tot + 1); tot = unique(map + 1, map + tot + 1) - map; for (int i = 1; i <= n; ++i) val[i] = lower_bound(map + 1, map + tot, val[i]) - map; // printf("tot = %d\n", tot); // // for (int i = 1; i < tot; ++i) // printf("%d ", map[i]); // puts(""); } int edge; int hd[siz]; int nt[siz]; int to[siz]; inline void initEdge(void) { edge = 0; memset(hd, -1, sizeof(hd)); // static int sz = sizeof(int); // memset(hd, -1, sz * (n + 5)); } inline void addEdge(int x, int y) { nt[edge] = hd[x]; to[edge] = y; hd[x] = edge++; nt[edge] = hd[y]; to[edge] = x; hd[y] = edge++; } int cnt; int root[siz]; int ls[siz * 20]; int rs[siz * 20]; int sm[siz * 20]; inline void initTree(void) { cnt = 0; memset(root, 0, sizeof(root)); // static int sz = sizeof(int); // memset(root, 0, sz * (n + 5)); } void insert(int &t, int f, int l, int r, int p, int v) { t = ++cnt; ls[t] = ls[f]; rs[t] = rs[f]; sm[t] = sm[f] + v; // printf("%d %d %d %d\n", t, l, r, sm[t]); if (l != r) { int mid = (l + r) >> 1; if (p <= mid) insert(ls[t], ls[f], l, mid, p, v); else insert(rs[t], rs[f], mid + 1, r, p, v); } } int fa[siz][25], dep[siz]; inline void initLCA(void) { memset(dep, 0, sizeof(dep)); // static int sz = sizeof(int); // memset(dep, 0, sz * (n + 5)); } inline int lca(int a, int b) { if (dep[a] < dep[b]) a ^= b ^= a ^= b; for (int i = 24; i >= 0; --i) if (dep[fa[a][i]] >= dep[b]) a = fa[a][i]; if (a == b)return a; for (int i = 24; i >= 0; --i) if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i]; return fa[a][0]; } int f[siz], g[siz]; inline void initUnion(void) { for (int i = 0; i <= n; ++i) f[i] = i, g[i] = 1; } inline int find(int u) { static int stk[siz], top = 0; while (f[u] != u) stk[++top] = u, u = f[u]; while (top) f[stk[top--]] = u; return u; } inline void Union(int a, int b) { if (!a)return; if (!b)return; a = find(a); b = find(b); if (a != b) { g[b] += g[a]; f[a] = b; } } void dfs(int u, int fr) { // printf("debug: dfs %d %d\n", u, fr); Union(u, fr); fa[u][0] = fr; dep[u] = dep[fr] + 1; for (int i = 1; i < 25; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1]; insert(root[u], root[fr], 1, tot, val[u], 1); for (int i = hd[u]; ~i; i = nt[i]) if (to[i] != fr)dfs(to[i], u); } int queA[siz], queB[siz], tail; inline void initQue(void) { tail = 0; } inline void addQue(int a, int b) { queA[tail] = root[a]; queB[tail++] = b; } int query(int l, int r, int k) { if (l == r)return l; int s = 0, mid = (l + r) >> 1; for (int i = 0; i < tail; ++i) s += sm[ls[queA[i]]] * queB[i]; if (s >= k) { for (int i = 0; i < tail; ++i) queA[i] = ls[queA[i]]; return query(l, mid, k); } else { for (int i = 0; i < tail; ++i) queA[i] = rs[queA[i]]; return query(mid + 1, r, k - s); } } int ans; signed main(void) { for (int cas = nextI(); cas--; ) { n = nextI(); m = nextI(); q = nextI(); for (int i = 1; i <= n; ++i) val[i] = nextI(); initMap(); initEdge(); initTree(); initUnion(); for (int i = 1; i <= m; ++i) { int x = nextI(); int y = nextI(); addEdge(x, y); } for (int i = 1; i <= n; ++i) if (g[find(i)] == 1) dfs(i, 0); // puts("debug: prework finished"); for (int i = 1; i <= q; ++i) { if (nextO()) // Query { int x = nextI() ^ ans; int y = nextI() ^ ans; int k = nextI() ^ ans; int t = lca(x, y); // printf("debug: lca %d %d = %d\n", x, y, t); initQue(); addQue(x, +1); addQue(y, +1); addQue(t, -1); addQue(fa[t][0], -1); // for (int i = 0; i < tail; ++i) // printf("que %d %d\n", queA[i], queB[i]); printf("%d\n", ans = map[query(1, tot, k)]); } else // Link { int x = nextI() ^ ans; int y = nextI() ^ ans; if (g[find(x)] > g[find(y)]) dfs(y, x); else dfs(x, y); } } } } /* 1 8 4 8 1 1 2 2 3 3 4 4 4 7 1 8 2 4 2 1 Q 8 7 3 Q 3 5 1 Q 10 0 0 L 5 4 L 3 2 L 0 7 Q 9 2 5 Q 6 1 6 */
View Code
@Author: YouSiki
相关文章推荐
- [BZOJ3123][Sdoi2013]森林(主席树启发式合并)
- [BZOJ3123][Sdoi2013]森林 主席树+启发式合并
- [BZOJ3123][Sdoi2013]森林:可持久化线段树+启发式合并
- 【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并
- [bzoj3123][SDOI2013]森林
- BZOJ 3123 SDOI2013 森林
- BZOJ 3123 SDOI2013 森林 可持久化线段树+倍增LCA+启发式合并
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
- 【bzoj3123】[Sdoi2013]森林 倍增LCA+主席树+启发式合并
- BZOJ 3123 [Sdoi2013]森林 主席树+启发式合并
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
- BZOJ3123 SDOI2013 森林
- 【bzoj3123】【sdoi2013】【森林】【启发式合并+主席树】
- 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并
- bzoj 3123: [Sdoi2013]森林 (主席树+启发式合并+并查集)
- [bzoj3123][SDOI2013]森林
- 【bzoj3123】 [Sdoi2013]森林
- bzoj 3123: [Sdoi2013]森林 启发式合并+可持久化线段树
- BZOJ 3123: [Sdoi2013]森林 启发式合并 树上主席树
- [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)