先对树DFS一边,建立dfs序列
tr[p].dep表示p的深度,tr[p].sz表示p的子树的大小(不包括p自己)
对dfs序列建立主席树乱搞= =
Claris大爷:"线段树中区间[a,b]表示深度在[a,b]范围内的sz的和"
貌似明白了>_<
Claris大爷又曰:"查询x,y的答案 = tr[x].sz * min(tr[x].dep, y) + dfs序在tr[x].L + 1到tr[x].R之间且深度在tr[x].dep + 1到tr[x].dep + k之间的sz的和"
于是就完了2333
1 /************************************************************** 2 Problem: 3653 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:9060 ms 7 Memory:111928 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 typedef long long ll; 15 const int N = 300005; 16 const int M = 5700000; 17 18 struct edges { 19 int next, to; 20 edges() {} 21 edges(int _next, int _to) : next(_next), to(_to) {} 22 }e[N << 1]; 23 24 struct segment_tree { 25 ll val; 26 int lson, rson; 27 }seg[M]; 28 29 struct tree_node { 30 int fa, dep, sz, L, R; 31 }tr[N]; 32 33 int n, Q; 34 int D; 35 int first[N], tot, cnt; 36 int q[N], TOT, root[N]; 37 38 inline int read() { 39 int x = 0; 40 char ch = getchar(); 41 while (ch < '0' || '9' < ch) 42 ch = getchar(); 43 while ('0' <= ch && ch <= '9') { 44 x = x * 10 + ch - '0'; 45 ch = getchar(); 46 } 47 return x; 48 } 49 50 inline void Add_Edges(int x, int y) { 51 e[++tot] = edges(first[x], y), first[x] = tot; 52 e[++tot] = edges(first[y], x), first[y] = tot; 53 } 54 55 void dfs(int p) { 56 int x, y; 57 tr[p].L = ++cnt; 58 q[cnt] = p; 59 for (x = first[p]; x; x = e[x].next) 60 if ((y = e[x].to) != tr[p].fa) { 61 tr[y].fa = p; 62 tr[y].dep = tr[p].dep + 1; 63 dfs(y); 64 tr[p].sz += tr[y].sz + 1; 65 } 66 tr[p].R = cnt; 67 } 68 69 int build(int p, int l, int r, int d, int sz) { 70 int y = ++TOT; 71 seg[y].val = seg[p].val + sz; 72 if (l == r) return y; 73 int mid = l + r >> 1; 74 if (d <= mid) 75 seg[y].lson = build(seg[p].lson, l, mid, d, sz), seg[y].rson = seg[p].rson; 76 else 77 seg[y].rson = build(seg[p].rson, mid + 1, r, d, sz), seg[y].lson = seg[p].lson; 78 return y; 79 } 80 81 ll query(int p, int l, int r, int L, int R) { 82 if (L <= l && r <= R) 83 return seg[p].val; 84 int mid = l + r >> 1; 85 ll res = 0; 86 if (L <= mid && seg[p].lson) 87 res += query(seg[p].lson, l, mid, L, R); 88 if (mid < R && seg[p].rson) 89 res += query(seg[p].rson, mid + 1, r, L, R); 90 return res; 91 } 92 93 inline void print(int x, int y) { 94 ll a = (ll) tr[x].sz * min(tr[x].dep, y), 95 b = query(root[tr[x].R], 0, D, tr[x].dep, tr[x].dep + y), 96 c = query(root[tr[x].L], 0, D, tr[x].dep, tr[x].dep + y); 97 printf("%lld\n", (ll) a + b - c); 98 } 99 100 int main() { 101 int i, X, Y; 102 n = read(), Q = read(); 103 for (i = 1; i < n; ++i) { 104 X = read(), Y = read(); 105 Add_Edges(X, Y); 106 } 107 dfs(1); 108 for (i = 1; i <= n; ++i) 109 D = max(D, tr[i].dep); 110 for (i = 1; i <= n; ++i) 111 root[i] = build(root[i - 1], 0, D, tr[q[i]].dep, tr[q[i]].sz); 112 while (Q--) { 113 X = read(), Y = read(); 114 print(X, Y); 115 } 116 return 0; 117 }
(p.s 竟然1WA,蒟蒻简直了。。。还查不错来,要了数据才发现我是沙茶,运算的时候要记得加上"(ll)")
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen