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;
    }
    
  • 相关阅读:
    JavaScript模态对话框类
    事件模块的演变(1)
    html5中可通过document.head获取head元素
    How to search for just a specific file type in Visual Studio code?
    What do 'lazy' and 'greedy' mean in the context of regular expressions?
    正则非获取匹配 Lookahead and Lookbehind ZeroLength Assertions
    regex length 正则长度问题
    Inversion of Control vs Dependency Injection
    How to return View with QueryString in ASP.NET MVC 2?
    今天才发现Google Reader
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11561305.html
Copyright © 2011-2022 走看看