洛谷 P3252 [JLOI2012]树

P3252 [JLOI2012]树

题目描述

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

输入输出格式

输入格式:

第一行是两个整数N和S,其中N是树的节点数。 第二行是N个正整数,第i个整数表示节点i的正整数。 接下来的N-1行每行是2个整数x和y,表示y是x的儿子。

输出格式:

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

输入输出样例

输入样例#1:

3 3
1 2 3
1 2
1 3

输出样例#1:

2

说明

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

思路:树上前缀和或者是爆搜

#include<iostream>
#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100100
using namespace std;
set<int>se;
int n,s,tot,ans;
int sum[MAXN],w[MAXN],dad[MAXN];
int to[MAXN*2],head[MAXN*2],net[MAXN*2];
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
}
void dfs(int now){
    sum[now]=sum[dad[now]]+w[now];
    se.insert(sum[now]);
    if(se.find(sum[now]-s)!=se.end())    ans++;
    for(int i=head[now];i;i=net[i])    dfs(to[i]);
    se.erase(sum[now]);
}
int main(){
    scanf("%d%d",&n,&s);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        dad[y]=x;
        add(x,y);
    }
    se.insert(0);
    dfs(1);
    cout<<ans;
}
时间: 2024-08-05 15:22:17

洛谷 P3252 [JLOI2012]树的相关文章

洛谷P3252 [JLOI2012]树

题目描述 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深度为1.路径不必一定从根节点开始. 输入输出格式 输入格式: 第一行是两个整数N和S,其中N是树的节点数. 第二行是N个正整数,第i个整数表示节点i的正整数. 接下来的N-1行每行是2个整数x和y,表示y是x的儿子. 输出格式: 输出路径节点总和为S的路径数量. 输入输出样例 输入样例#1: 3 3 1 2 3

洛谷P3018 [USACO11MAR]树装饰Tree Decoration

洛谷P3018 [USACO11MAR]树装饰Tree Decoration树形DP 因为要求最小,我们就贪心地用每个子树中的最小cost来支付就行了 1 #include <bits/stdc++.h> 2 #define For(i, j, k) for(int i=j; i<=k; i++) 3 #define Dow(i, j, k) for(int i=j; i>=k; i--) 4 #define LL long long 5 using namespace std;

[模板]洛谷T3372 线段树 模板1

变量定义: sum[]:线段树节点对应区间的元素总和: addv[]:线段树节点对应区间的所有元素的待追加值(懒标记),初值全部设为0. 过程说明: 建树(Build): 若当前节点仅包含原序列中的一个值,即L=R,则直接赋值为序列中该值,否则递归建立左右子树后,将左右子树保存的sum值相加,即得到当前节点的sum值. 懒标记下放(Push_down): 将当前节点的addv值下放到左右子树. 细节实现: 1.子树的addv值加上当前节点的addv值: 2.子树的sum值加上(子树包含元素数量*

[模板]洛谷T3373 线段树 模板2

此题相对于模板一,加了个区间乘,于是在模板一的基础上需要多开个数组(记录乘法懒标记).多写个函数(区间乘),还有要把懒标记下放函数做些修改. 变量定义: sum[]:线段树节点对应区间的元素总和: addv[]:线段树节点对应区间的所有元素待加的值(懒标记),初值全部设为0: mulv[]:线段树节点对应区间的所有元素待乘的值(懒标记),初值全部设为1. 过程说明: 建树(Build): 同模板一... 懒标记下放(Push_down): 原理解释: 1.当对某区间执行加法操作时,由于加法优先级

洛谷 P2590 [ZJOI2008]树的统计

题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 输入输出格式 输入格式: 输入文件的第一行为一个整数n,表示节点的个数. 接下来n – 1行,每行2个整数a和b,表示节点a和节点b之

洛谷—— P1873 砍树

https://www.luogu.org/problemnew/show/P1873 题目描述 伐木工人米尔科需要砍倒M米长的木材.这是一个对米尔科来说很容易的工作,因为他有一个漂亮的新伐木机,可以像野火一样砍倒森林.不过,米尔科只被允许砍倒单行树木. 米尔科的伐木机工作过程如下:米尔科设置一个高度参数H(米),伐木机升起一个巨大的锯片到高度H,并锯掉所有的树比H高的部分(当然,树木不高于H米的部分保持不变).米尔科就行到树木被锯下的部分. 例如,如果一行树的高度分别为20,15,10和17,

洛谷P3372线段树模板1——线段树

题目:https://www.luogu.org/problemnew/show/P3372 线段树模板. 代码如下: #include<iostream> #include<cstdio> using namespace std; long long n,m,a[100005],ct; struct N{ long long lazy,sum; long long ls,rs; }p[200005]; void pushdown(long long cur,long long l

洛谷.4114.Qtree1(树链剖分)

题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N=1e5+5; int n,m,cnt,ep[N],W[N],

洛谷 P3979 遥远的国度(树链剖分)

题目描述 修改某条路径上的值以及询问子树的最小值都是最树剖的基础操作,那么如何实现换根呢? 考虑一下三种情况: 1.rot=询问的子树x,答案就是整棵树的最小值 2.rot在x的子树里,只有rot到x这一条链上的的节点的子树会变 找到x在rot方向上的子节点,答案就是除去这棵子树的最小值 3.rot不在x的子树里,那么rot是谁对x的子树没有影响,答案不变 那么就在询问时分类讨论一下就好了 #include<complex> #include<cstdio> using names