bzoj2783 [JLOI2012]树

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。

 

正解:$set$启发式合并。

题面鬼得不行。。

比较简单的一个题,直接在树上用启发式合并即可,我偷懒所以写了个$multiset$。。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define N (200010)
 6 
 7 using namespace std;
 8 
 9 struct edge{ int nt,to; }g[N<<1];
10 
11 int head[N],val[N],son[N],sz[N],rt[N],tim[N],num,n,S;
12 ll ans;
13 
14 multiset<int> st[N];
15 
16 multiset<int>:: iterator it;
17 
18 il int gi(){
19   RG int x=0,q=1; RG char ch=getchar();
20   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
21   if (ch=='-') q=-1,ch=getchar();
22   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
23   return q*x;
24 }
25 
26 il void insert(RG int from,RG int to){
27   g[++num]=(edge){head[from],to},head[from]=num; return;
28 }
29 
30 il void dfs(RG int x,RG int p){
31   sz[x]=1; RG int v,tr;
32   for (RG int i=head[x];i;i=g[i].nt){
33     v=g[i].to; if (v==p) continue;
34     dfs(v,x),sz[x]+=sz[v];
35     if (sz[son[x]]<=sz[v]) son[x]=v;
36   }
37   if (val[x]==S) ++ans;
38   if (!son[x]){ rt[x]=x,st[x].insert(val[x]); return; }
39   rt[x]=rt[son[x]],tim[rt[x]]+=val[x],tr=rt[x];
40   ans+=st[tr].count(S-tim[tr]);
41   for (RG int i=head[x],Rt,d;i;i=g[i].nt){
42     v=g[i].to; if (v==p || v==son[x]) continue; Rt=rt[v];
43     for (it=st[Rt].begin();it!=st[Rt].end();++it){
44       d=(*it)+tim[Rt]+val[x]; if (d==S) ++ans;
45       if (d<=S) st[tr].insert(d-tim[tr]);
46     }
47     st[Rt].clear();
48   }
49   st[tr].insert(val[x]-tim[tr]); return;
50 }
51 
52 int main(){
53 #ifndef ONLINE_JUDGE
54   freopen("tree.in","r",stdin);
55   freopen("tree.out","w",stdout);
56 #endif
57   n=gi(),S=gi();
58   for (RG int i=1;i<=n;++i) val[i]=gi();
59   for (RG int i=1,x,y;i<n;++i)
60     x=gi(),y=gi(),insert(x,y),insert(y,x);
61   dfs(1,0),cout<<ans; return 0;
62 }

 

posted @ 2017-09-27 19:27  wfj_2048  阅读(254)  评论(0编辑  收藏  举报