zoukankan      html  css  js  c++  java
  • bzoj2809 可并堆(左偏树)

    HYSBZ - 2809

    题意:给你一颗树,每个节点有2个权值,li表示该点的领导力,ci表示花费,选择一个子树,该子树的根作为领导,然后从这个子树下选出x个节点,所有选出的节点的花费和不大于m,得到一个价值为 领导力乘选出的节点数, 即ans=li*x,求最大值

    思路:首先可以知道的是当选出了一个子树时,只要贪心得在这颗子树下每次取出花费最小的即可,直到总花费大于m,即可以dfs每次选出一个子树,先将所有点选取,然后每次删除花费最大的节点,直到总花费不大于m,用可并堆维护即可

    AC代码:

    #include "iostream"
    #include "iomanip"
    #include "string.h"
    #include "stack"
    #include "queue"
    #include "string"
    #include "vector"
    #include "set"
    #include "map"
    #include "algorithm"
    #include "stdio.h"
    #include "math.h"
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
    #define mem(a,x) memset(a,x,sizeof(a))
    #define step(x) fixed<< setprecision(x)<<
    #define mp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define ll long long
    #define endl ("
    ")
    #define ft first
    #define sd second
    #define lrt (rt<<1)
    #define rrt (rt<<1|1)
    using namespace std;
    const ll mod=1e9+7;
    const ll INF = 1e18+1LL;
    const int inf = 1e9+1e8;
    const double PI=acos(-1.0);
    const int N=1e5+100;
    
    int rt[N], ls[N], rs[N], d[N], siz[N], val[N], cnt = 0;
    int head[N], to[N], nex[N], li[N], tot;
    int n, M;
    ll ans, sum[N];
    void add(int u, int v) {
        to[tot] = v;
        nex[tot] = head[u];
        head[u] = tot++;
    }
    
    void updata(int x) {
        siz[x] = siz[ls[x]]+siz[rs[x]]+1;
        sum[x] = sum[ls[x]]+sum[rs[x]]+val[x];
        if(d[ls[x]] < d[rs[x]]) swap(ls[x], rs[x]);
        if(!rs[x]) d[x] = 0;
        else d[x] = d[rs[x]] + 1;
    }
    
    int Merge(int x, int y) {
        if(!x || !y) return x+y;
        if(val[x] < val[y]) swap(x, y);
        rs[x] = Merge(y, rs[x]);
        updata(x);
        return x;
    }
    
    void pop(int &x) {
        int last = x;
        x = Merge(ls[x], rs[x]);
        ls[last] = rs[last] = d[last] = 0;
    }
    
    void dfs(int u) {
        rt[u] = u, siz[u] = 1, sum[u] = val[u];
        for(int i=head[u]; i!=-1; i=nex[i]) {
            int v = to[i];
            dfs(v);
            rt[u] = Merge(rt[u], rt[v]);
        }
        while(siz[rt[u]] && sum[rt[u]] > M) pop(rt[u]);
        ans = max(ans, (ll)siz[rt[u]]*(ll)li[u]);
    }
    
    int main(){
        scanf("%d %d", &n, &M);
        mem(head, -1);
        int root = 0;
        for(int i=1; i<=n; ++i) {
            int b, c, l;
            scanf("%d %d %d", &b, &c, &l);
            val[i] = c, li[i] = l;
            add(b, i);
            if(b == 0) root = i;
        }
        dfs(root);
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    docker常规操作——启动、停止、重启容器实例
    docker同时删除多个容器
    ubuntu中使用docker部署.netcore2.1
    .NET中RabbitMQ的使用
    Java开发环境Jave EE 和 jdk 下载
    WebApi用户登录验证及服务器端用户状态存取
    MVC中使用Ninject依赖注入
    起步:SpringBoot
    ML-对偶(Duality)问题 KKT 条件
    pandas 之 多层索引
  • 原文地址:https://www.cnblogs.com/max88888888/p/8859184.html
Copyright © 2011-2022 走看看