• uoj#33. 【UR #2】树上GCD


    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
    ",s+dc[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jquery的promise和es6的promise的区别
    vue源码
    Paging through lots of data efficiently (and in an Ajax way) with ASP.NET 2.0
    laydate 1.1 下拉日期挡住的bug修复
    Microsoft SQL Server 2008 R2 官方简体中文正式版下载(附激活序列号密钥)
    使用ASP.NET Treeview显示数据库里DataTable里的数据。
    [C# .NET] 数组排序 Arrays
    字符串数据按照大小排序
    Chrome浏览器中的三种刷新模式
    『TensorFlow』lookup.index_table_from_tensor查找表映射函数
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7365518.html
Copyright © 2020-2023  润新知