[luoguP3252] [JLOI2012]树(DP)

传送门

树上前缀和。

在树上找一条权值和为 s 的链,其中这个链上的点按深度递增(递减)(不同)

dfs

每搜到一个点求它的前缀和 sum[x],放入 set 中。

在 set 中找 sum[x] - s 的点,如果有,ans++

退出 dfs 的时候再把 sum[x] 从 set 中删除

因为每个点权都是正整数,所以 set 中没有重复元素。

同时也是单调递增,所以简单些不用 set,开个数组再 lower_bound 也行。

——代码

 1 #include <set>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5
 6 const int MAXN = 100001;
 7 int n, s, cnt, ans;
 8 int a[MAXN], head[MAXN], to[MAXN << 1], next[MAXN << 1], f[MAXN], sum[MAXN];
 9 std::set <int> S;
10
11 inline int read()
12 {
13     int x = 0, f = 1;
14     char ch = getchar();
15     for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
16     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
17     return x * f;
18 }
19
20 inline void add(int x, int y)
21 {
22     to[cnt] = y;
23     next[cnt] = head[x];
24     head[x] = cnt++;
25 }
26
27 inline void dfs(int u)
28 {
29     sum[u] = sum[f[u]] + a[u];
30     S.insert(sum[u]);
31     if(S.count(sum[u] - s)) ans++;
32     for(int i = head[u]; i ^ -1; i = next[i]) dfs(to[i]);
33     S.erase(sum[u]);
34 }
35
36 int main()
37 {
38     int i, x, y;
39     n = read();
40     s = read();
41     memset(head, -1, sizeof(head));
42     for(i = 1; i <= n; i++) a[i] = read();
43     for(i = 1; i < n; i++)
44     {
45         x = read();
46         y = read();
47         f[y] = x;
48         add(x, y);
49     }
50     S.insert(0);
51     dfs(1);
52     printf("%d\n", ans);
53     return 0;
54 }

时间: 2024-12-11 16:56:14

[luoguP3252] [JLOI2012]树(DP)的相关文章

2010辽宁省赛 NBUT 1222 English Game【字典树+DP】

[1222] English Game 时间限制: 1000 ms 内存限制: 131072 K 链接:Click Here! 问题描述 This English game is a simple English words connection game. The rules are as follows: there are N English words in a dictionary, and every word has its own weight v. There is a wei

uva 12452 Plants vs. Zombies HD SP (树DP)

Problem I: Plants vs. Zombies HD Super Pro Plants versus Zombies HD Super Pro is a game played not a grid, but on a connected graph G with no cycles (i.e., a tree). Zombies live on edges of the tree and chew through edges so that tree falls apart! Pl

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #inclu

洛谷 P3252 [JLOI2012]树

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

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 220000 #define inf 0x3ffffffffffffffLL typedef long long ll; int v[N],e[N],ne[N],nn,w[N]; void add(int x,int y,int z){ ne[++nn

【BZOJ2783】[JLOI2012]树 DFS+栈+队列

[BZOJ2783][JLOI2012]树 Description 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深度为1.路径不必一定从根节点开始. Input 第一行是两个整数N和S,其中N是树的节点数. 第二行是N个正整数,第i个整数表示节点i的正整数. 接下来的N-1行每行是2个整数x和y,表示y是x的儿子. Output 输出路径节点总和为S的路径数量. Sa

【HDU 5647】DZY Loves Connecting(树DP)

pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 332    Accepted Submission(s): 112 Problem Description DZY has an unroote