Codeforces Round #381 (Div. 2) D. Alyona and a tree 树型前缀和+二分维护

来源:互联网 发布:淘宝代运营骗局举报 编辑:程序博客网 时间:2024/06/05 07:20

题意:给一棵有向树,根固定为1,每个顶点v都有一个权值av。对于每个顶点,若其他顶点满足dist(v, u) ≤ au   ,则u能被v控制。注意u是子树节点。要求输出每个顶点控制的顶点个数。

解法:刚开始看错了题目,想要二分却维护不了单调性,后来发现u、v中u才是子树节点(和平时做题的命名习惯不太一样哈)。这样就能很好想到二分了。dfs的时候,系统栈里存的其实是一条链式的路径,所以就在这条路径上二分长度,维护一个从每一个叶子节点到根节点这些路径的答案前缀和就行。

#include <bits/stdc++.h>using namespace std;#define fst first#define snd secondtypedef long long ll;typedef unsigned int uii;typedef pair<ll,int> pli;const int maxn=200005;int n,v,res[maxn];ll a[maxn],w;vector<pli> vec[maxn],pa;void dfs(int u,int fa,ll dep) {    int id=lower_bound(pa.begin(),pa.end(),pli(dep-a[u],-1))-pa.begin();    if (id-1>=0)        --res[pa[id-1].snd];    pa.push_back(pli(dep,u));    res[u]=1;    for (uii i=0;i<vec[u].size();++i) {        if (fa==vec[u][i].snd)            continue;        dfs(vec[u][i].snd,u,dep+vec[u][i].fst);        res[u]+=res[vec[u][i].snd];    }    pa.pop_back();}int main(){    scanf("%d",&n);    for (int i=1;i<=n;++i)        scanf("%lld",&a[i]);    for (int i=2;i<=n;++i) {        scanf("%d%lld",&v,&w);        vec[i].push_back(pli(w,v));        vec[v].push_back(pli(w,i));    }    dfs(1,0,0);    for (int i=1;i<=n;++i)        printf("%d%c",res[i]-1,i==n?'\n':' ');    return 0;}


1 0
原创粉丝点击