http://codeforces.com/problemset/problem/293/E
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef __int64 LL;
const int N=1e5+10;
struct Edge{
int v,next,w;
Edge(int v=-1,int next=-1,int w=-1):v(v),next(next),w(w){}
}e[N*2];
int head[N],total;
void init(){
memset(head,-1,sizeof(head));total=0;
}
void adde(int u,int v,int w){
e[total]=Edge(v,head[u],w);head[u]=total++;
}
int ss[N],sz,s[N];s[i]以i为根的节点个数,ss[i]以i为根的子树中最大节点个数,sz整棵树的节点个数
int down[N];/下推标记
int root;重心
void getroot(int u,int f){ss[] s[]
s[u]=1;ss[u]=0;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v!=f&&!down[v]){
getroot(v,u);
s[u]+=s[v];
ss[u]=max(ss[u],s[v]);
}
}
ss[u]=max(ss[u],sz-s[u]);
if(ss[u]<ss[root])root=u;
}
struct PP{
int h,w;
PP(int h=-1,int w=-1):h(h),w(w){}
bool operator<(const PP&th)const {
return w<th.w;
}
}pp[N];
int cd;
int ww[N],hh[N];/到根的距离
void getdep(int u,int f){dis[] s[]
pp[cd++]=PP(hh[u],ww[u]);
s[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(!down[v]&&v!=f){
hh[v]=hh[u]+1;ww[v]=ww[u]+w;
getdep(v,u);
s[u]+=s[v];
}
}
}
int n,H,W;
int cc[N];
void update(int x,int v){
while(x<=n){
cc[x]+=v;x+=x&-x;
}
}
void dele(int x){
while(x<=n)cc[x]=0,x+=x&-x;
}
int query(int x){
int ans=0;
while(x>0){
ans+=cc[x];x-=x&-x;
}
return ans;
}
LL cal(int u,int w1,int w2){///dep[]
cd=0;hh[u]=w1;ww[u]=w2;
getdep(u,0);
LL ret=0;
sort(pp,pp+cd);
int j=0;update(pp[0].h,1);
for(int i=cd-1;i>=1;i--){
if(pp[i].w+pp[0].w>W)continue;
while(j>i-1){
update(pp[j].h,-1);j--;
}
while(j+1<=i-1&&pp[i].w+pp[j+1].w<=W){
j++;update(pp[j].h,1);
}
ret+=query(min(H+2-pp[i].h,n));
}
while(j>=0){
update(pp[j].h,-1);j--;
}
return ret;
}
LL ans=0;
void work(int u){sz root ans;
ans+=cal(u,1,0);
down[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(!down[v]){
ans-=cal(v,2,w);
ss[0]=sz=s[v];
getroot(v,root=0);
work(root);
}
}
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
while(scanf("%d%d%d",&n,&H,&W)!=EOF){
init();
for(int i=2;i<=n;i++){
int v,w;scanf("%d%d",&v,&w);
adde(i,v,w);adde(v,i,w);
}
ans=0;
memset(cc,0,sizeof(cc));
memset(down,0,sizeof(down));
ss[0]=sz=n;
getroot(1,root=0);
work(root);
printf("%I64d\n",ans);
}
return 0;
}
点分治
最新推荐文章于 2022-05-06 13:16:49 发布