Codechef 12.7 DGCD 数学+树链剖分+线段树

 

Codechef 13.12 QTREE6 树链剖分+线段树

 

UOJ#30 图连通性+树链剖分+线段树

 

Codechef 13.11MONOPLOY LCT+树链剖分+线段树

 

BZOJ3011:[Usaco2012 Dec]Running Away From the Barn 树链剖分

思路:

对于每一个点,它会对自己的一段连续的祖先造成影响.

因此我们就可以用树链剖分维护即可.

(不知道有什么简单写法,我明明没写线段树啊...)

(也许是某种奇怪的单调性,但我不想想这么多了...)

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