bzoj 2783: [JLOI2012]树 dfs+二分

来源:互联网 发布:pytorch 知乎 编辑:程序博客网 时间:2024/05/18 02:58

题意

给定一个值S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到S。路径中节点的深度必须是升序的。假设节点1是根节点,根的深度是0,它的儿子节点的深度为1。路径不必一定从根节点开始。
S<=1000,n<=100000

分析

处理一个树上前缀和,用一个栈维护根节点到当前节点的路径序列,每次二分查找即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 100005using namespace std;int n,s,cnt,last[N],a[N],st[N],top,ans;struct edge{int to,next;}e[N*2];void addedge(int u,int v){    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void dfs(int x,int fa,int now){    st[++top]=now;    int w=lower_bound(st+1,st+top+1,now-s)-st;    if (st[w]==now-s&&w>0&&w<=top) ans++;    for (int i=last[x];i;i=e[i].next)    {        if (e[i].to==fa) continue;        dfs(e[i].to,x,now+a[e[i].to]);    }    top--;}int main(){    scanf("%d%d",&n,&s);    for (int i=1;i<=n;i++)        scanf("%d",&a[i]);    for (int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        addedge(x,y);    }    st[++top]=0;    dfs(1,0,a[1]);    printf("%d",ans);    return 0;}
0 0