Close Vertices
Codeforces 293E
求路径,你懂的点分它
1.权值可能会很大,但是l小于等于n。所以可以考虑枚举链的权值,查询长度
2.存下链的长度和权值和,按权值排序。从大到小枚举,从小到大往BIT里塞长度,当A[i].val+A[j].val<=w时把A[j]塞入BIT。即在BIT的A[j].l处。
具体代码如下:
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
int n,W,LL;
int head[M],asdf;
long long ans;
struct edge {
int to,cost,nxt;
} G[M*2];
void add_edge(int a,int b,int c) {
G[++asdf].to=b;
G[asdf].nxt=head[a];
G[asdf].cost=c;
head[a]=asdf;
}
struct BIT {
int sum[M];
void add(int x,int a) {
while(x<=n) {
sum[x]+=a;
x+=-x&x;
}
}
int query(int x) {
int tot=0;
while(x>0) {
tot+=sum[x];
x-=-x&x;
}
return tot;
}
} BIT;
bool mark[M];
int que[M],sz[M],son[M],que_len;
void get_root(int x,int f) {
que[++que_len]=x;
sz[x]=1;
son[x]=0;
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(y==f||mark[y])continue;
get_root(y,x);
sz[x]+=sz[y];
son[x]=max(son[x],sz[y]);
}
}
int len;
struct node {
int l,val;
bool operator <(const node &tmp)const {
return val<tmp.val;
}
} dis[M];
void get_dis(int x,int f,int l,int val) {
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(y==f||mark[y])continue;
dis[++len]=(node) {
l+1,val+G[i].cost
};
get_dis(y,x,l+1,val+G[i].cost);
}
}
void calc(int t) {
sort(dis+1,dis+1+len);//从小到大
int l1=1;
long long sum=0;
for(int i=len; i>=1; i--) { //从大到小枚举边
if(t>0) {
if(dis[i].l<=LL&&dis[i].val<=W)ans++;
}
if(dis[i].val+dis[i].val<=W&&dis[i].l+dis[i].l<=LL)sum--;
while(l1<=len&&dis[l1].val+dis[i].val<=W) {
BIT.add(dis[l1].l,1);//从小到大加边
l1++;
}
sum+=BIT.query(LL-dis[i].l);
}
ans+=t*sum/2;
while(l1-1>0) {
l1--;
BIT.add(dis[l1].l,-1);
}
}
void solve(int x) {
que_len=0;
get_root(x,x);
for(int i=1; i<=que_len; i++) {
son[que[i]]=max(son[que[i]],que_len-sz[que[i]]);
if(son[que[i]]<son[x])x=que[i];
}
mark[x]=1;
len=0;
get_dis(x,x,0,0);
calc(1);
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(mark[y])continue;
len=0;
dis[++len]=(node) {
1,G[i].cost
};
get_dis(y,x,1,G[i].cost);
calc(-1);
solve(y);
}
}
int main() {
scanf("%d %d %d",&n,&LL,&W);
int a,c;
for(int i=2; i<=n; i++) {
scanf("%d %d",&a,&c);
add_edge(a,i,c);
add_edge(i,a,c);
}
solve(1);
printf("%I64d\n",ans);
return 0;
}