CF1009F Dominant Indices

长链剖分

一个dp

dp[i][j]距离i节点的子树中为j的节点数

#include<bits/stdc++.h>

using namespace std;
const int N=1e6+7;
//长链剖分 
int head[N],nxt[N<<1],to[N<<1];

int _;
void add(int x,int y)
{
    _++;
    to[_]=y;    
    nxt[_]=head[x];
    head[x]=_;
    return ;
}
int n;
vector<int>dp[N];
//dp[x][i]表示x的子树中深度为i的点个数 

int son[N];
//到节点i距离为j的节点数 
int dep[N];
void dfs1(int x,int fa)
{

    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==fa)
        continue;
        dfs1(y,x);
        if(dep[y]>=dep[son[x]])
        {//寻找长儿子,与轻重链剖分类似 
            son[x]=y;    
            dep[x]=dep[y]+1;//继承深度 
        }
    }

    return ;
}
int ans[N];
int cnt;
void solve(int x,int fa)
{
    if(son[x])
    {//如果有长儿子 
        solve(son[x],x);
        //优先处理长儿子 
        swap(dp[x],dp[son[x]]);
        //注意深度 
        dp[x].push_back(1);
        ans[x]=ans[son[x]];
        //层层递传 
        if(dp[x][ans[x]]==1)
        ans[x]=dep[x];
        //到底了,记录 

        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(y==fa||y==son[x])
            continue;//长儿子已处理 
            solve(y,x);
            
            for(int j=dep[y];j>=0;j--)
            {//分配空间 
                int tmp=j+dep[x]-dep[y]-1;
                //tmp当个指针 
                dp[x][tmp]+=dp[y][j];
                //普通儿子直接暴力合并
                //长儿子利用tmp指针,+1 
                if(dp[x][tmp]>dp[x][ans[x]]||(dp[x][tmp]==dp[x][ans[x]]&&tmp>ans[x]))
                 ans[x]=tmp;    
            }
        }
        
    }
    
    else
    {
        //建 
        dp[x].push_back(1);
        ans[x]=0;
    }

    return ; 
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int q,w;
        cin>>q>>w;
        add(q,w);
        add(w,q);
    }

    dfs1(1,0);
    // 建树 
    solve(1,0);
    
    for(int i=1;i<=n;i++)
    cout<<dep[i]-ans[i]<<endl;
    return 0;
 } 

 

上一篇:PCL平面检测SAC


下一篇:Leetcode 833. Find And Replace in String