http://codeforces.com/problemset/problem/740/D
对于每一对<u, v>。设dis[u]表示root到点u的距离,那么dis<u去v>就是dis[v] - dis[u],
就是在它的儿子中找出有多少个v使得dis[v] - dis[u] <= a[v]。然后,因为如果v确定了,那么dis[v]和a[v]就确定了。
所以把公式转换为dis[v] - a[v] <= dis[u]。
那么可以暴力枚举每一个u,然后在其儿子中找有多少个数小于等于它,这个可以直接暴力分块。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 2e5 + 20; struct node { int u, v, w; int tonext; }e[maxn]; int first[maxn]; int num; void add(int u, int v, int w) { ++num; e[num].u = u; e[num].v = v; e[num].w = w; e[num].tonext = first[u]; first[u] = num; } int a[maxn]; int ans[maxn]; LL dp[maxn]; struct LIST { int id; LL val; }List[maxn]; int lenList; int DFN; int L[maxn]; int R[maxn]; void dfs(int cur) { List[++lenList].id = cur; // List[lenList].val = a[cur]; ++DFN; L[cur] = DFN; for (int i = first[cur]; i; i = e[i].tonext) { int v = e[i].v; dp[v] = dp[e[i].u] + e[i].w; dfs(v); } R[cur] = DFN; } LL tosort[maxn]; void work() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } for (int i = 1; i <= n - 1; ++i) { int fa, w; scanf("%d%d", &fa, &w); add(fa, i + 1, w); } dfs(1); for (int i = 1; i <= lenList; ++i) { List[i].val = dp[List[i].id] - a[List[i].id]; tosort[i] = List[i].val; // printf("%d ", List[i].id); // printf("%d %d\n", L[List[i].id], R[List[i].id]); } int magic = (int)sqrt(lenList); for (int i = 1; i <= lenList;) { if (i + magic - 1 <= lenList) { sort(tosort + i, tosort + i + magic); } else break; i += magic; } for (int i = 1; i <= n; ++i) { for (int j = L[i] + 1; j <= R[i];) { if (j % magic == 1 && j + magic - 1 <= R[i]) { int pos = upper_bound(tosort + j, tosort + j + magic, dp[i]) - (tosort + j - 1); ans[i] += pos - 1; j += magic; } else { if (dp[i] >= List[j].val) { ans[i]++; } j++; } } } for (int i = 1; i <= n; ++i) { printf("%d ", ans[i]); } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }
时间: 2024-10-13 03:45:19