CF1009F Dominant Indices - 题解

CF1009F Dominant Indices
题意:
求每棵子树中深度为k的子孙最多的k,有多个k取最小。
做法:
显然的DP是 $ f[i][j] $ 表示在i的子树内深度为j的点的个数,然而这样是 $ O(n^2) $ 的。
由于这道题与深度有关,所以考虑长链剖分。对于长链,直接继承孩子在长链上的答案。对于长链顶点,暴力向上DP转移,所以空间和时间复杂度都为所有长链的长度和,是 $ O(n) $ 的。

#include<bits/stdc++.h>
#define pb push_back
#define rep(i,a,b) for(int i=(a),i##ed=(b);i<=i##ed;i++)
#define per(i,a,b) for(int i=(a),i##ed=(b);i>=i##ed;i--)
using namespace std;
const int N=1000010;
int n; vector<int> e[N];
int dep[N],son[N],ans[N];
int f[N],dfn[N],idx,tp;

int Max(int x,int y) { return x>y? x:y; }
void dfs1(int u,int ff) {
    dep[u]=1;
    rep(i,0,e[u].size()-1) {
        int v=e[u][i]; if(v==ff) continue;
        dfs1(v,u),dep[u]=Max(dep[u],dep[v]+1);
        if(dep[son[u]]<dep[v]) son[u]=v;
    }
}
void dfs2(int u,int ff) {
    dfn[u]=++idx,ans[u]=0,f[dfn[u]]=1;
    if(son[u]) dfs2(son[u],u),ans[u]=ans[son[u]]+1;
    if(ans[u]==1) ans[u]=0;
    rep(i,0,e[u].size()-1) {
        int v=e[u][i]; if(v==ff||v==son[u]) continue;
        dfs2(v,u);
        rep(j,0,dep[v]-1) {
            f[dfn[u]+j+1]+=f[dfn[v]+j];
            if(f[dfn[u]+j+1]>f[dfn[u]+ans[u]]||
              (j+1<ans[u]&&f[dfn[u]+j+1]==f[dfn[u]+ans[u]]))
                ans[u]=j+1;
        }
    }
}
int main() {
    scanf("%d",&n);
    rep(i,2,n) { int x,y;scanf("%d%d",&x,&y),e[x].pb(y),e[y].pb(x); }
    dfs1(1,0),dfs2(1,0); rep(i,1,n) printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/daniel14311531/p/10458628.html