BZOJ3011:[Usaco2012 Dec]Running Away From the Barn 树链剖分
Feb 02, 2015 04:05:10 PM
思路:
对于每一个点,它会对自己的一段连续的祖先造成影响.
因此我们就可以用树链剖分维护即可.
(不知道有什么简单写法,我明明没写线段树啊...)
(也许是某种奇怪的单调性,但我不想想这么多了...)
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
#define N 200010
int pa[N][18];LL d[N][18];
namespace Fio{
inline int getc(){
static const int L=1<<15;static char buf[L],*S=buf,*T=buf;
if(S==T){T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;}
return*S++;
}
inline bool digit(char c){return c>='0'&&c<='9';}
template<typename T>inline void Get(T&x){
int c;while(!digit(c=getc()));x=c-'0';while(digit(c=getc()))x=(x<<1)+(x<<3)+c-'0';
}
char buf[200010*20],*o=buf;
template<typename T>inline void print(T x){
static int stk[21];int top=0;
if(!x)*o++=48;else{for(;x;x/=10)stk[++top]=x%10;for(int i=top;i>=1;--i)*o++=48+stk[i];}
*o++='\n';
}
inline void final(){fwrite(buf,1,o-buf,stdout);}
}
int head[N],next[N],end[N];
inline void addedge(int a,int b){static int q=1;end[q]=b,next[q]=head[a],head[a]=q++;}
int siz[N],son[N],dep[N];
void Build(int x){
int Mx=0;siz[x]=1;
for(int j=head[x];j;j=next[j]){
dep[end[j]]=dep[x]+1,Build(end[j]);
if(Mx<siz[end[j]])Mx=siz[end[j]],son[x]=end[j];
siz[x]+=siz[end[j]];
}
}
int top[N],pid[N],idp[N],cnt;
void Create(int x,int Top){
top[x]=Top,idp[pid[x]=++cnt]=x;
if(son[x])Create(son[x],Top);
for(int j=head[x];j;j=next[j])if(end[j]!=son[x])Create(end[j],end[j]);
}
int ans[N];
inline void cover(int l,int r){
ans[l]++,ans[r+1]--;
}
inline void work(int x,int y){
while(top[x]!=top[y]){
if(dep[x]<dep[y])swap(x,y);
cover(pid[top[x]],pid[x]),x=pa[top[x]][0];
}
if(dep[x]<dep[y])swap(x,y);
cover(pid[y],pid[x]);
}
int res[N];
int main(){
#ifndef ONLINE_JUDGE
freopen("tt.in","r",stdin);
#endif
int n;LL l;Fio::Get(n),Fio::Get(l);
register int i,j;for(i=2;i<=n;++i)Fio::Get(pa[i][0]),Fio::Get(d[i][0]),addedge(pa[i][0],i);
for(j=1;j<=17;++j)for(i=1;i<=n;++i)pa[i][j]=pa[pa[i][j-1]][j-1],d[i][j]=d[i][j-1]+d[pa[i][j-1]][j-1];
dep[1]=1,Build(1),Create(1,1);
int anc,nowdep;LL nowd;
for(i=1;i<=n;++i){
nowd=0,nowdep=dep[i],anc=i;
for(j=17;j>=0;--j)if(nowdep-(1<<j)>=1&&nowd+d[anc][j]<=l)nowdep-=(1<<j),nowd+=d[anc][j],anc=pa[anc][j];
work(anc,i);
}
int get=0;
for(i=1;i<=n;++i)res[idp[i]]=get+=ans[i];
for(i=1;i<=n;++i)Fio::print(res[i]);
return Fio::final(),0;
}