【BZOJ 2588】Count on a tree
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
Input
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
Output
M行,表示每个询问的答案。
Sample Input
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
Sample Output
2
8
9
105
7
8
9
105
7
HINT
N,M<=100000
暴力自重。。。
分析:
可持久化线段树,以父亲的版本为基础创建儿子的版本,结合LCA就可以了。(最后多了个\n居然给我格式错误QAQ)
代码:
1 #include <cstdio> 2 #include <algorithm> 3 4 const int maxn = 500000; 5 const int maxm = 2000000; 6 7 int et[maxn], ep[maxn], last[maxn], en; 8 int ch[maxm][2], Count[maxm]; 9 int root[maxm], size; 10 int n, m, u, v, w, lca, ans; 11 int deep[maxn], fa[maxn][20]; 12 int num[maxn], id[maxn], back[maxn]; 13 14 void ins (int a, int b) 15 { 16 en++; 17 ep[en] = last[a]; 18 last[a] = en; 19 et[en] = b; 20 } 21 22 #define MID (left + (right - left >> 1)) 23 24 25 int modify (int left, int right, int pos, int prev) 26 { 27 int i = ++size; 28 if (left < right) 29 { 30 int c = pos > MID; 31 ch[i][!c] = ch[prev][!c]; 32 c ? left = MID + 1 : right = MID; 33 ch[i][c] = modify (left, right, pos, ch[prev][c]); 34 Count[i] = Count[ch[i][0]] + Count[ch[i][1]]; 35 }else Count[i] = 1; 36 return i; 37 } 38 39 #define LEFTSIZE (Count[ch[l1][0]] + Count[ch[l2][0]] - Count[ch[e1][0]] - Count[ch[e2][0]]) 40 41 int query (int left, int right, int e1, int e2, int l1, int l2, int k) 42 { 43 if (left == right) return num[id[left]]; 44 int c = k > LEFTSIZE; 45 c ? left = MID + 1 : right = MID; 46 return query (left, right, ch[e1][c], ch[e2][c], ch[l1][c], ch[l2][c], c ? k - LEFTSIZE : k); 47 } 48 49 bool cmp (int a, int b) 50 { 51 return num[a] < num[b]; 52 } 53 54 void dfs (int i, int p) 55 { 56 deep[i] = deep[p] + 1; 57 fa[i][0] = p; 58 for (int b = 0; fa[i][b]; b++) 59 fa[i][b + 1] = fa[fa[i][b]][b]; 60 root[i] = modify (1, n, back[i], root[p]); 61 for (int e = last[i]; e; e = ep[e]) 62 if (deep[et[e]] == 0) dfs (et[e], i); 63 } 64 65 int find (int i, int j) 66 { 67 int k, b; 68 if (deep[i] > deep[j]) 69 i ^= j, j ^= i, i ^= j; 70 for (k = deep[j] - deep[i], b = 0; k; k >>= 1, b++) 71 k & 1 ? j = fa[j][b] : 1; 72 if (i == j) return i; 73 for (b = 0; fa[i][b] != fa[j][b]; b++); 74 for (b--; ~b; b--) if (fa[i][b] != fa[j][b]) i = fa[i][b], j = fa[j][b]; 75 return fa[i][0]; 76 } 77 78 int main () 79 { 80 scanf ("%d %d", &n, &m); 81 for (int i = 1; i <= n; i++) 82 scanf ("%d", &num[i]), id[i] = i; 83 std::sort (id + 1, id + n + 1, cmp); 84 for (int i = 1; i <= n; i++) 85 back[id[i]] = i; 86 for (int i = 1; i < n; i++) 87 { 88 scanf ("%d %d", &u, &v); 89 int flag = last[id[1]] > 0; 90 ins (u, v); ins (v, u); 91 } 92 dfs (1, 0); 93 ans = 0; 94 for (int i = 0; i < m; i++) 95 { 96 scanf ("%d %d %d", &u, &v, &w); 97 u ^= ans; 98 lca = find (u, v); 99 ans = query (1, n, root[fa[lca][0]], root[lca], root[u], root[v], w); 100 if (i) printf ("\n"); 101 printf ("%d", ans); 102 } 103 }
Your eyes light up the world when you smile.