• 题解 洛谷 P1552 【[APIO2012]派遣】


    根据题意,我们不难发现忍者之间的关系是树形结构。

    发现答案的统计只是在该节点的子树中,因此我们考虑通过树形(DP)来解决问题。

    从叶子节点开始,从下往上考虑,因为一个节点的最优答案只与他的领导力和在子树中选了几个点有关,与选哪些点无关,所以我们要最大化选点的个数。

    贪心策略即为尽可能的多选点,当选出的点的薪水超过预算时,删去当前选出的点中薪水最大的点,通过这样的策略来保证我们能选出最多的点。

    通过可并堆(左偏树)来实现,同时维护一些信息,选出点的薪水总和(sum),选出点的个数(siz)

    其他的一些细节就看代码吧,统计答案记得开(long long)

    (code:)

    #include<bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll n,m,root,ans;
    ll fa[maxn],ls[maxn],rs[maxn],dis[maxn],val[maxn],l[maxn],sum[maxn],siz[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int merge(int x,int y)
    {
        if(x==y) return 0;
        if(!x||!y) return x+y;
        if(val[x]<val[y]) swap(x,y);
        rs[x]=merge(rs[x],y),fa[rs[x]]=x;
        if(dis[ls[x]]<dis[rs[x]]) swap(ls[x],rs[x]);
        if(rs[x]) dis[x]=dis[rs[x]]+1;
        else dis[x]=0;
        return x;
    }
    void del(int x)
    {
        fa[ls[x]]=ls[x],fa[rs[x]]=rs[x];
        fa[x]=merge(ls[x],rs[x]);
    }
    void dfs(int x)
    {
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            dfs(y);
            siz[x]+=siz[y];
            sum[x]+=sum[y];
            merge(find(x),find(y));
        }
        while(sum[x]>m)
        {
            int rootx=find(x);
            siz[x]--;
            sum[x]-=val[rootx];
            del(rootx);
        }
        ans=max(ans,l[x]*siz[x]);
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;++i)
        {
            int fath;
            read(fath),read(val[i]),read(l[i]);
            sum[i]=val[i],siz[i]=1,fa[i]=i;
            if(fath) add(fath,i);
            else root=i;
        }
        dfs(root);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    40个你可能不知道的Python的特点和技巧
    Python Streaming实战2: Join的实现与数据过滤
    python + Streaming框架的MR实践与优化
    python编码最佳实践之总结
    Python自然语言处理系列之模拟退火算法
    Python自然语言处理
    机器学习实践中的 7 种常见错误
    玩转python主题模型程序库gensim
    Python自然语言处理
    glusterfs
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229824.html
Copyright © 2020-2023  润新知