• CF1059E Split the Tree(树形DP,倍增,树上DFS序二分)


    CF1059E Split the Tree(树形DP,倍增,树上DFS序二分)

    题目链接:CF1059E

    我们可以先倍增预处理出从每个结点向上最多能延伸多长,用 $len[u]$ 表示

    我们再观察一下DP方程 $f[u]=max (f[v])$ , $num[u]=sum num[v]$ $(fa[v]=u)$

    如果当前点 $f[u]=-1$,则 $f[u]=len[u]-1,num[u]++$

    #include<bits/stdc++.h>
    #define MAXN 100010
    using namespace std;
    typedef long long ll;
    inline ll read ()
    {
        ll s=0,w=1;
        char ch=getchar ();
        while (ch<'0'||ch>'9'){if (ch=='-') w=-1;ch=getchar ();}
        while ('0'<=ch&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar ();
        return s*w;
    }
    struct edge{
        int v,nxt;
    }e[MAXN<<1];
    int n,l,cnt;
    ll s,w[MAXN],dis[MAXN];
    int head[MAXN],mi[21];
    int F[MAXN][21],dep[MAXN],fa[MAXN],len[MAXN];
    int f[MAXN],num[MAXN];
    void add (int u,int v)
    {
        e[++cnt].v=v;
        e[cnt].nxt=head[u];
        head[u]=cnt;
    }
    void dfs (int u,int ff)
    {
        dis[u]=dis[ff]+w[u],dep[u]=dep[ff]+1;
        F[u][0]=ff,fa[u]=ff;
        for (int i=1;mi[i]<=dep[u];i++)
            F[u][i]=F[F[u][i-1]][i-1];
        for (int i=head[u];i!=0;i=e[i].nxt)
            dfs (e[i].v,u);
    }
    void DFS (int u)
    {
        f[u]=-1;
        for (int i=head[u];i!=0;i=e[i].nxt)
        {
            DFS (e[i].v);
            num[u]+=num[e[i].v];
            f[u]=max (f[u],f[e[i].v]-1);
        }
        if (f[u]==-1) f[u]=len[u]-1,num[u]++;
    }
    int main()
    {
        mi[0]=1;for (int i=1;i<=20;i++) mi[i]=mi[i-1]<<1;
        n=read (),l=read (),s=read ();
        for (int i=1;i<=n;i++)
        {
            w[i]=read ();
            if (w[i]>s)
            {
                printf ("-1");
                return 0;
            }
        }
        for (int i=2;i<=n;i++) add (read (),i);
        dfs (1,0);
        for (int i=1;i<=n;i++)
        {
            int u=i;
            for (int j=20;j>=0;j--)
                if (F[u][j]!=0&&dis[i]-dis[fa[F[u][j]]]<=s&&dep[i]-dep[fa[F[u][j]]]<=l) u=F[u][j];
            len[i]=dep[i]-dep[u]+1;
        }
        DFS (1);
        printf ("%d",num[1]);
        return 0;
    }

    在这里我们可以发现一个优美的性质

    我们可以按照dfs栈的顺序,在栈里二分,因为在 $u$ 时,栈中存的是有序的 $u$ 结点的祖先

    可以以更小的空间消耗和时间消耗完成这道题。

  • 相关阅读:
    iOS 9适配系列教程:后台定位
    入行几年后,互联网人的未来应该在哪里?
    iOS iOS8注册通知
    Warning!程序员们小心被技术绑架
    2015 Objective-C 三大新特性
    怎么面试架构师
    移动Web资源整理
    利用微信提高APP下载的3个推广方式!
    Audio Session Programming Guide
    iOS 设计
  • 原文地址:https://www.cnblogs.com/PaulShi/p/10079008.html
Copyright © 2020-2023  润新知