前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ2783: [JLOI2012]树(树上前缀和+set)

BZOJ2783: [JLOI2012]树(树上前缀和+set)

作者头像
attack
发布2018-04-13 15:49:48
5170
发布2018-04-13 15:49:48
举报

Description

数列

提交文件:sequence.pas/c/cpp

输入文件:sequence.in

输出文件:sequence.out

问题描述:

把一个正整数分成一列连续的正整数之和。这个数列必须包含至少两个正整数。你需要求出这个数列的最小长度。如果这个数列不存在则输出-1。

输入格式:

每行包含一个正整数n。

每个文件包含多行,读入直到文件结束。

输出格式:

对于每个n,输出一行,为这个数列的最小长度。

       第一行是两个整数N和S,其中N是树的节点数。

       第二行是N个正整数,第i个整数表示节点i的正整数。

       接下来的N-1行每行是2个整数x和y,表示y是x的儿子。

输出格式:

       输出路径节点总和为S的路径数量。

输入样例:

输出样例:

3 3 1 2 3 1 2 1 3

2

数据范围:

对于30%数据,N≤100;

对于60%数据,N≤1000;

对于100%数据,N≤100000,所有权值以及S都不超过1000。

数据范围:

对于所有数据,n≤263。

这个是JLOI2012的T1,发出来仅为了试题完整

=============================================================================================

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

Input

       第一行是两个整数N和S,其中N是树的节点数。

       第二行是N个正整数,第i个整数表示节点i的正整数。

       接下来的N-1行每行是2个整数x和y,表示y是x的儿子。

Output

       输出路径节点总和为S的路径数量。

Sample Input

3 3 1 2 3 1 2 1 3

Sample Output

2

HINT

对于100%数据,N≤100000,所有权值以及S都不超过1000。

Source

刚开始以为是点分治,但是这道题目明确说明所有的路径都是一条链

然后来一遍树上前缀和就行了!

注意不要忘了删除

#include<cstdio>
#include<set>
#include<algorithm>
#include<cstring>
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
char buf[1<<23],*p1=buf,*p2=buf;
using namespace std;
const int MAXN=1e6+10;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int N,S;
int val[MAXN],sum[MAXN],ans=0;
set<int>s;
struct node
{
    int u,v,nxt;
}edge[MAXN];
int head[MAXN],num=1;
inline void AddEdge(int x,int y)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].nxt=head[x];
    head[x]=num++;
}
int dfs(int now)
{
    s.insert(sum[now]);
    if(s.find(sum[now]-S)!=s.end()) ans++;
    for(int i=head[now];i!=-1;i=edge[i].nxt)
    {
        sum[edge[i].v]=sum[now]+val[edge[i].v];
        dfs(edge[i].v);
    }
    s.erase(s.find(sum[now]));
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #endif
    N=read(),S=read();
    memset(head,-1,sizeof(head));
    for(int i=1;i<=N;i++) val[i]=read();
    for(int i=1;i<=N-1;i++)
    {
        int x=read(),y=read();
        AddEdge(x,y);
    }
    sum[1]=val[1];
    //s.insert(0);
    dfs(1);
    printf("%d",ans);
    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Description
  • Input
  • Output
  • Sample Input
  • Sample Output
  • HINT
  • Source
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档