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; }