1. 程式人生 > >bzoj2783 [JLOI2012]樹

bzoj2783 [JLOI2012]樹

iterator != script while 多行 開始 bsp long scrip

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 }

bzoj2783 [JLOI2012]樹