3653: 谈笑风生
Posted mjtcn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3653: 谈笑风生相关的知识,希望对你有一定的参考价值。
3653: 谈笑风生
分析:
$ans = min(deep[x] - 1, k) * siz[x] - 1 +sumlimits_{y是u子树内的点}(siz[y] - 1)$
前面的可以$O(1)$算,后面的那一部分可以dfs序+主席树维护。
或者dfs的过程中+线段树合并。或者长链剖分。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; } const int N = 600005; struct Edge{ int to, nxt; } e[N << 1]; int head[N], deep[N], fa[N], siz[N], st[N], ed[N], tr[N], En, Index, TimeIndex; int ls[N * 20], rs[N * 20], Root[N]; LL sum[N * 20]; inline void add_edge(int u,int v) { ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En; ++En; e[En].to = u, e[En].nxt = head[v]; head[v] = En; } void dfs(int u) { deep[u] = deep[fa[u]] + 1; siz[u] = 1; st[u] = ++TimeIndex;tr[TimeIndex] = u; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == fa[u]) continue; fa[v] = u; dfs(v); siz[u] += siz[v]; } ed[u] = TimeIndex; } void update(int l,int r,int last,int &now,int p) { if (!now) now = ++Index; sum[now] += sum[last] + siz[tr[p]] - 1; /// !!! if (l == r) return ; int mid = (l + r) >> 1; if (deep[tr[p]] <= mid) { rs[now] = rs[last]; update(l, mid, ls[last], ls[now], p); } else { ls[now] = ls[last]; update(mid + 1, r, rs[last], rs[now], p); } } LL query(int l,int r,int last,int now,int L,int R) { if (L <= l && r <= R) return sum[now] - sum[last]; int mid = (l + r) >> 1; LL res = 0; if (L <= mid) res = query(l, mid, ls[last], ls[now], L, R); if (R > mid) res += query(mid + 1, r, rs[last], rs[now], L, R); return res; } int main() { int n = read(), Q = read(), D; for (int i = 1; i < n; ++i) { int u = read(), v = read(); add_edge(u, v); } dfs(1); for (int i = 1; i <= n; ++i) D = max(D, deep[i]); for (int i = 1; i <= n; ++i) { update(1, D, Root[i - 1], Root[i], i); } LL ans = 0; while (Q--) { int x = read(), k = read(); ans = 1ll * min(deep[x] - 1, k) * (siz[x] - 1); if (deep[x] < D) ans += query(1, D, Root[st[x]], Root[ed[x]], deep[x] + 1, min(D, deep[x] + k)); printf("%lld ", ans); } return 0; }
以上是关于3653: 谈笑风生的主要内容,如果未能解决你的问题,请参考以下文章