先对树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 }
View Code

(p.s 竟然1WA,蒟蒻简直了。。。还查不错来,要了数据才发现我是沙茶,运算的时候要记得加上"(ll)")

posted on 2014-11-20 15:04  Xs酱~  阅读(335)  评论(2编辑  收藏  举报