ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://uoj.ac/problem/33

长链剖分,每条链用类似分块的方式维护深度%x=y的个数,可以自底向上合并信息。

#include<bits/stdc++.h>
typedef long long i64;
const int N=2e5+7;
char rb[N*12],*rp=rb;
int _(){
    int x=0;
    while(*rp<48)++rp;
    while(*rp>47)x=x*10+*rp++-48;
    return x;
}
std::vector<int>e[N];
int n,md[N],top[N],dep[N],dc[N];
i64 ans[N];
inline void maxs(int&a,int b){if(a<b)a=b;}
inline bool cmp_md(int a,int b){return md[a]<md[b];}
template<class T>
inline T*$(int L,int R){
    static T mem[N*5],*mp=mem;
    T*r=mp-L;
    mp+=R-L+1;
    return r;
}
struct dat{
    int mx,B,*d1,**d2,*d3;
    void ins(int x,int y){
        for(int i=1;i<=B;++i)d2[i][x%i]+=y;
        d1[x]+=y;
    }
    int que(int x,int y){
        if(x<=B)return d2[x][y];
        int s=0;
        if(!y)y=x;
        for(int i=y;i<=mx;i+=x)s+=d1[i];
        return s;
    }
    void init(int n){
        B=sqrt(mx=n);
        d1=$<int>(1,mx);
        d2=$<int*>(1,B);
        for(int i=1;i<=B;++i)d2[i]=$<int>(0,i-1);
    }
    void cal(){
        d3=$<int>(1,mx);
        for(int i=1;i<=mx;++i){
            for(int j=i;j<=mx;j+=i)d3[i]+=d1[j];
        }
    }
    void mg1(dat&w){
        for(int i=1;i<=w.mx;++i){
            d1[i]+=w.d1[i];
            ans[i]+=i64(d3[i])*w.d3[i];
            d3[i]+=w.d3[i];
        }
    }
    void mg2(dat&w,int d){
        for(int i=1;i<=w.mx;++i){
            ans[i]+=i64(w.d3[i])*que(i,d%i);
        }
        for(int i=1;i<=w.mx;++i){
            ins(d+i,w.d1[i]);
        }
    }
}ds[N];
void f1(int w){
    ++dc[dep[w]];
    for(int i=0;i<e[w].size();++i){
        int u=e[w][i];
        dep[u]=dep[w]+1;
        f1(u);
        maxs(md[w],md[u]+1);
    }
    std::sort(e[w].begin(),e[w].end(),cmp_md);
}
void f2(int w,int tp){
    top[w]=tp;
    if(e[w].empty())ds[tp].init(dep[w]-dep[tp]+1);
    else{
        int sz=e[w].size();
        f2(e[w][sz-1],tp);
        if(sz>1){
            int u;
            for(int i=0;i<sz-1;++i){
                u=e[w][i];
                f2(u,u);
                ds[u].cal();
                if(i)ds[u].mg1(ds[e[w][i-1]]);
            }
            u=e[w][sz-2];
            ds[tp].mg2(ds[u],dep[u]-dep[tp]);
        }
    }
    ds[tp].ins(dep[w]-dep[tp]+1,1);
}
int ps[N/5],pp=0,mu[N];
bool np[N];
int main(){
    fread(rb,1,sizeof(rb),stdin);
    n=_();
    mu[1]=1;
    for(int i=2;i<=n;++i){
        if(!np[i])ps[pp++]=i,mu[i]=-1;
        for(int j=0,k;j<pp&&(k=i*ps[j])<=n;++j){
            np[k]=1;
            if(i%ps[j])mu[k]=-mu[i];
            else break;
        }
    }
    for(int i=2;i<=n;++i)e[_()].push_back(i);
    f1(1);
    f2(1,1);
    for(int i=n;i;--i)dc[i]+=dc[i+1];
    for(int i=1;i<n;++i){
        i64 s=0;
        for(int j=i,k=1;j<=n;j+=i,++k)s+=ans[j]*mu[k];
        printf("%lld\n",s+dc[i]);
    }
    return 0;
}
View Code

 

posted on 2017-08-15 15:49  nul  阅读(370)  评论(0编辑  收藏  举报