zoukankan      html  css  js  c++  java
  • CF1009F Dominant Indices

    讲一下长链剖分。
    类似于重链剖分,我们将一棵树分成多条重链。
    对于每个点,其重儿子(也可以称为长儿子)是到叶子节点距离最远的点。
    然后类似于静态链分治,我们在计算某个点的答案时先计算重儿子,然后直接继承重儿子答案,再暴力合并轻儿子答案。
    为了实现空间与时间复杂的的降低,我们需要用指针来实现。
    长链剖分的时间复杂度为(O(n))
    考虑每条重链,仅会在其链顶被暴力合并一次、
    而重链的长度总和为(O(n))
    所以复杂度为(O(n))
    Link
    首先这题有一个非常显然的(dp)
    (f_{u,i})(u)的子树中深度为(i)的点的个数,(S_u)(u)的子树。
    那么(f_{u,0}=1,f_{u,i}=sumlimits_{vin S_u}f_{v,i-1})
    然后我们考虑长链剖分,并且把(f)开成指针数组。
    对于重儿子,我们直接指针赋一下值,答案加个一即可。
    对于轻儿子,我们暴力合并。
    实现过程中,我们开一个长度为(n)(tmp)数组,每条长链分配(len_u)(u)是这条长链的顶点)的空间,具体用指针实现。

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
    namespace IO
    {
        char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
        void Put(char x){*oS++=x;if(oS==oT)Flush();}
        int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
        void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
    ');}
    }
    using namespace IO;
    const int N=1000007;
    vector<int>G[N];
    int len[N],son[N],t[N],*f[N],*id=t,ans[N],n;
    void dfs(int u,int fa)
    {
        for(int v:G[u]) if(v^fa) dfs(v,u),son[u]=len[v]>len[son[u]]? v:son[u];
        len[u]=len[son[u]]+1;
    }
    void dp(int u,int fa)
    {
        f[u][0]=1;
        if(son[u]) f[son[u]]=f[u]+1,dp(son[u],u),ans[u]=ans[son[u]]+1;
        for(int v:G[u])
        {
            if(v==fa||v==son[u]) continue;
            f[v]=id,id+=len[v],dp(v,u);
            for(int j=1;j<=len[v];++j)
    	{
                f[u][j]+=f[v][j-1];
                if((j<ans[u]&&f[u][j]>=f[u][ans[u]])||(j>ans[u]&&f[u][j]>f[u][ans[u]])) ans[u]=j;
            }
        }
        if(f[u][ans[u]]==1) ans[u]=0;
    }
    int main()
    {
        n=read();int i,u,v;
        for(i=1;i<n;++i) u=read(),v=read(),G[u].pb(v),G[v].pb(u);
        dfs(1,0),f[1]=id,id+=len[1],dp(1,0);
        for(i=1;i<=n;++i) write(ans[i]);
        return Flush(),0;
    }
    
  • 相关阅读:
    poj2192
    poj2002
    poj2190
    poj2001
    poj2195
    自我成长:20岁到40岁的简单人生规划
    最容易让人失恋的十种职业
    职场发展的5W问题(对我影响很大)
    你个人知识管理了吗?
    安慰人的10大原则——当不知该说什么时
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11561305.html
Copyright © 2011-2022 走看看