bzoj3653: 谈笑风生
设sz为子树大小,根的深度为1.
显然答案为min(dep[p] - 1, k) * (sz[p] - 1) + sigma(sz[u], u在p的子树中,dep[u] - dep[p] <= k)
对于加号右边,对两个区间的限制条件询问信息,可以考虑可持久化线段树,但不同版本间的信息必须满足区间减法。
具体是dfs序在外面还是深度在外面无所谓(深度最大值<=n,所以用深度常数会小?)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstring> 6 #include<string> 7 8 using namespace std; 9 10 void setIO(const string& a) { 11 freopen((a + ".in").c_str(), "r", stdin); 12 freopen((a + ".out").c_str(), "w", stdout); 13 } 14 15 typedef long long LL; 16 const int N = 300000 + 10, logn = 20; 17 18 struct Node *pis, *null; 19 20 struct Node { 21 LL s; 22 Node* ch[2]; 23 24 Node(LL s = 0) : s(s) { 25 ch[0] = ch[1] = null; 26 } 27 28 void *operator new(size_t) { 29 return pis++; 30 } 31 }*root[N], pool[N * logn]; 32 33 #define mid (l + ((r - l) >> 1)) 34 #define ls x->ch[0], y->ch[0], l, mid 35 #define rs x->ch[1], y->ch[1], mid + 1, r 36 37 void build(Node*& x, Node *y, int l, int r, int key, int val) { 38 x = new Node(*y), x->s += val; 39 if(l == r) return; 40 if(key <= mid) build(ls, key, val); else build(rs, key, val); 41 } 42 43 LL query(Node *x, Node *y, int l, int r, int lft, int rgt) { 44 if(lft <= l && r <= rgt) return y->s - x->s; 45 LL res = 0; 46 if(lft <= mid) res += query(ls, lft, rgt); 47 if(mid < rgt) res += query(rs, lft, rgt); 48 return res; 49 } 50 51 #undef mid 52 #undef ls 53 #undef rs 54 55 int dfs_seq[N], pre[N], end[N], sz[N], dep[N], dfs_clk, max_dep; 56 57 #include<vector> 58 vector<int> G[N]; 59 void AddEdge(int u, int v) { 60 G[u].push_back(v); 61 G[v].push_back(u); 62 } 63 64 void dfs(int u) { 65 max_dep = max(max_dep, dep[u]); 66 dfs_seq[++dfs_clk] = u; 67 pre[u] = dfs_clk; 68 sz[u] = 1; 69 for(unsigned i = 0; i < G[u].size(); ++i) { 70 int v = G[u][i]; 71 if(dep[v]) continue; 72 dep[v] = dep[u] + 1; 73 dfs(v); 74 sz[u] += sz[v]; 75 } 76 end[u] = dfs_clk; 77 } 78 79 int main() { 80 #ifdef DEBUG 81 freopen("in.txt", "r", stdin); 82 freopen("out.txt", "w", stdout); 83 #endif 84 85 pis = pool; 86 int n, m; 87 scanf("%d%d", &n, &m); 88 for(int i = 1; i < n; i++) { 89 int u, v; 90 scanf("%d%d", &u, &v); 91 AddEdge(u, v); 92 } 93 94 dep[1] = 1, dfs(1); 95 96 // cerr << max_dep << endl; 97 98 root[0] = null = new Node(0); 99 null->ch[0] = null->ch[1] = null; 100 101 for(int i = 1; i <= n; i++) { 102 build(root[i], root[i - 1], 1, max_dep, dep[dfs_seq[i]], sz[dfs_seq[i]] - 1); 103 } 104 105 for(int i = 1; i <= m; i++) { 106 int p, k; 107 scanf("%d%d", &p, &k); 108 LL res = (LL) min(dep[p] - 1, k) * (sz[p] - 1); 109 res += query(root[pre[p]], root[end[p]], 1, max_dep, dep[p] + 1, min(dep[p] + k, max_dep)); 110 printf("%lld\n", res); 111 } 112 113 return 0; 114 }
原文出处http://www.cnblogs.com/showson/