首页 > 代码库 > 【CF739B】Alyona and a tree(树上差分,二分,树形DP)

【CF739B】Alyona and a tree(树上差分,二分,树形DP)

题意:给出一棵有根树,树上每个点、每条边都有一个权值。

现在给出“控制”的定义:对一个点u,设点v在其子树上,且dis(u,v)av,则称u控制v。

要求求出每个点控制了多少个点

n (1?≤?n?≤?2·105).  (1?≤?ai?≤?109) 1?≤?pi?≤?n1?≤?wi?≤?109) 

思路:在学校CF有时上不去不知道为什么

对于确定的点i,计算它对哪些点有贡献

dis[i]-dis[u]<=a[i]

dis[u]<=a[i]-dis[i]满足二分性

倍增枚举深度最小的i能给它贡献的点j

树上差分部分就是 inc(fa[i]) dec(fa[j])

最后统计出来的答案就是它子树里的和

注意INT64

 1 var f:array[0..210000,0..19]of longint;
 2     head,vet,next,len,flag,a:array[0..410000]of longint;
 3     dp,dep,dis:array[0..410000]of int64;
 4     n,tot,i,x,y,l,r,mid,last,j:longint;
 5  
 6 procedure add(a,b,c:longint);
 7 begin
 8  inc(tot);
 9  next[tot]:=head[a];
10  vet[tot]:=b;
11  len[tot]:=c;
12  head[a]:=tot;
13 end;
14  
15 procedure dfs(u:longint);
16 var e,v,i:longint;
17 begin
18  flag[u]:=1;
19  for i:=1 to 19 do
20  begin
21   if dep[u]<(1<<i) then break;
22   f[u,i]:=f[f[u,i-1],i-1];
23  end;
24  e:=head[u];
25  while e<>0 do
26  begin
27   v:=vet[e];
28   if flag[v]=0 then
29   begin
30    dep[v]:=dep[u]+1;
31    dis[v]:=dis[u]+len[e];
32    f[v,0]:=u;
33    dfs(v);
34   end;
35   e:=next[e];
36  end;
37 end;
38  
39 procedure dfs2(u:longint);
40 var e,v:longint;
41 begin
42  flag[u]:=1;
43  e:=head[u];
44  while e<>0 do
45  begin
46   v:=vet[e];
47   if flag[v]=0 then
48   begin
49    dfs2(v);
50    dp[u]:=dp[u]+dp[v];
51   end;
52   e:=next[e];
53  end;
54 end;
55  
56 function clac(x,y:longint):longint;
57 var i:longint;
58 begin
59  for i:=0 to 19 do
60   if y and (1<<i)>0 then x:=f[x,i];
61  exit(x);
62 end;
63  
64 begin
65  //assign(input,cf739B.in); reset(input);
66  //assign(output,cf739B.out); rewrite(output);
67  readln(n);
68  for i:=1 to n do read(a[i]);
69  for i:=2 to n do
70  begin
71   readln(x,y);
72   add(i,x,y);
73   add(x,i,y);
74  end;
75  dfs(1);
76  fillchar(flag,sizeof(flag),0);
77  for i:=1 to n do
78  begin
79   l:=1; r:=dep[i]; last:=i;
80   while l<=r do
81   begin
82    mid:=(l+r)>>1;
83    j:=clac(i,mid);
84    if dis[i]-dis[j]<=a[i] then begin last:=j; l:=mid+1; end
85     else r:=mid-1;
86   end;
87   dec(dp[f[last,0]]);
88   inc(dp[f[i,0]]);
89  end;
90  
91  dfs2(1);
92  for i:=1 to n-1 do write(dp[i], );
93  write(dp[n]);
94  //close(input);
95  //close(output);
96 end.

 

【CF739B】Alyona and a tree(树上差分,二分,树形DP)