编程爱好者联盟 2017-02-17
题目大意:
给出一棵树,每条边有权值,求经过少于l条边,权值和少于w的路径总数。
点分治。每次求出所有点到重心的距离,按w排序,然后维护一个树状数组,记录经过的边<=i的点个数。由于可能两个点都在一棵子树中,再容斥一下就好了。
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 inline char nc(){
7 static char buf[100000],*p1=buf,*p2=buf;
8 if(p1==p2){
9 p2=(p1=buf)+fread(buf,1,100000,stdin);
10 if(p1==p2)return EOF;
11 }
12 return *p1++;
13 }
14 inline void Read(int& x){
15 char c=nc();
16 for(;c<'0'||c>'9';)c=nc();
17 for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
18 }
19 #define N 100001
20 #define lowbit(x) x&-x
21 #define ll long long
22 struct Edge{
23 int t,nx,w;
24 }e[N<<1];
25 struct Node{
26 int d,w;
27 }a[N];
28 int i,j,k,n,m,h[N],f[N],L,w,Son[N],Sum,Num,x,y,t,c[N],Rt,l,r,M;
29 bool b[N];
30 ll Ans;
31 inline void Add(int x,int y,int z){
32 e[++Num].t=y;e[Num].w=z;e[Num].nx=h[x];h[x]=Num;
33 }
34 inline int _Max(int x,int y){return x>y?x:y;}
35 inline int _Min(int x,int y){return x>y?y:x;}
36 inline bool Cmp(Node a,Node b){return a.w<b.w;}
37 inline void Update(int x,int y){if(x==0)return;for(;x<=M;x+=lowbit(x))c[x]+=y;}
38 inline int Query(int x){int Ans=0;for(;x>0;x-=lowbit(x))Ans+=c[x];return Ans;}
39 inline void Get_root(int x,int F){
40 f[x]=0;Son[x]=1;
41 for(int i=h[x];i;i=e[i].nx){
42 int v=e[i].t;
43 if(e[i].t==F||b[e[i].t])continue;
44 Get_root(e[i].t,x);Son[x]+=Son[e[i].t];
45 f[x]=_Max(f[x],Son[e[i].t]);
46 }
47 f[x]=_Max(f[x],Sum-Son[x]);
48 if(f[x]<f[Rt])Rt=x;
49 }
50 inline void Dfs(int x,int F,int y,int z){
51 if(F!=0){a[++t].d=y;a[t].w=z;M=_Max(M,y);}
52 for(int i=h[x];i;i=e[i].nx){
53 int v=e[i].t;
54 if(v==F||b[v])continue;
55 Dfs(v,x,y+1,z+e[i].w);
56 }
57 }
58 inline ll Calc(int x,int y,int z,bool Flag){
59 t=M=0;if(Flag)Dfs(x,0,y,z);else Dfs(x,-1,y,z);
60 sort(a+1,a+t+1,Cmp);
61 l=1;r=t;ll Ans=0;
62 for(int i=1;i<=M;i++)c[i]=0;
63 for(int i=l;i<=r;i++)Update(a[i].d,1);
64 if(Flag)for(int i=l;i<=r;i++)if(a[i].w<=w&&a[i].d<=L)Ans++;
65 while(l<r)
66 if(a[l].w+a[r].w<=w){
67 Update(a[l].d,-1);
68 Ans+=Query(_Min(L-a[l++].d,M));
69 }else Update(a[r--].d,-1);
70 return Ans;
71 }
72 inline void Solve(int x){
73 b[x]=1;
74 Ans+=Calc(x,0,0,1);
75 for(int i=h[x];i;i=e[i].nx){
76 int v=e[i].t;
77 if(b[v])continue;
78 Ans-=Calc(v,1,e[i].w,0);
79 f[Rt=0]=n+1;Sum=Son[v];Get_root(v,0);
80 Solve(Rt);
81 }
82 }
83 int main()
84 {
85 Read(n);Read(L);Read(w);
86 for(i=1;i<n;i++){
87 Read(x);Read(y);
88 Add(i+1,x,y);
89 Add(x,i+1,y);
90 }
91 f[Rt=0]=n+1;Sum=n;Get_root(1,0);
92 Solve(Rt);
93 printf("%I64d",Ans);
94 return 0;
95 } codeforces293E