# 【BZOJ 2588】Count on a tree

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

2
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 }

posted @ 2015-04-03 13:09  Lightning34  阅读(173)  评论(0编辑  收藏  举报