739B Codeforces Alyona and a tree 树上差分+二分(倍增)

来源:互联网 发布:qq飞车noble数据 编辑:程序博客网 时间:2024/05/18 21:43

题目大意是给出一棵有根树,树上每个点、每条边都有一个权值。

现在给出“控制”的定义:对一个点u,设点v在其子树上,且dis(u,v)av,则称u控制v。

要求求出每个点控制了多少个点

模拟dfs过程,我们很容易发现dfs到点u时,其祖先节点到根的dis值都已经算出,且是单调递增,所以我们可以用二分或者倍增,在log的时间复杂度内找到深度最小的满足dis(u,v)au的点了。找到点v后,v到fa(u)上的每个点的答案都要增加1,显然用树上差分来实现,对ans[fa[v]]–,ans[fa[u]]++

#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;const int maxn = 200010;const int lg = 20;int n;long long a[maxn];long long c[maxn];struct edge{    int v,w,next;}e[maxn << 1];long long dep[maxn];int h[maxn],num = 0;int f[maxn][lg+1];int u,v;long long w;void build(int u,int v,int w){    num++;    e[num].v = v;    e[num].w = w;    e[num].next = h[u];    h[u] = num;}void dfs1(int x,int fa){    int v;    f[x][0] = fa;    for(int i = 1; i < lg; i++)        f[x][i] = f[f[x][i-1]][i-1];    int u = x;    for(int i = lg - 1; i >= 0; i--)        while(u > 1 && dep[x] - dep[f[u][i]] <= a[x])            u = f[u][i];    u = max(1,u);    c[f[u][0]]--;    c[f[x][0]]++;    for(int i = h[x]; i; i = e[i].next)    {        v = e[i].v;        if(v != fa)        {            dep[v] = dep[x] + e[i].w;            dfs1(v,x);        }    }}void dfs2(int x,int f){    int v;    for(int i = h[x]; i; i = e[i].next)    {        v = e[i].v;        if(v != f)        {            dfs2(v,x);            c[x] += c[v];        }    }}int main(){    freopen("1.in","r",stdin);    cin >> n;    for(int i = 1; i <= n; i++)        scanf("%I64d",&a[i]);    for(int i = 2; i <= n; i++)    {        scanf("%d%I64d",&v,&w);        build(i,v,w);        build(v,i,w);    }    dfs1(1,0);    dfs2(1,0);    for(int i = 1; i <= n; i++)        printf("%I64d%c",c[i],i == n ? '\n' : ' ');    return 0;}
0 0
原创粉丝点击