zoukankan      html  css  js  c++  java
  • bzoj2809: [Apio2012]dispatching

    题目链接

    bzoj2809: [Apio2012]dispatching

    题解

    领导关系形成一棵树,那么答案为(ans=max{L[u] imes k}),其中k代表以u为根的子树中选出的节点数个数(设这些节点为(v_1,v_2cdots v_k)且有(sum_{i=1}^{k}C[v_i]leq M)

    每个节点建一个大根堆,维护薪水值。初始时若自己满足条件就选自己,否则不选。从叶子节点往上推,对于每个节点,将它与它的儿子节点合并。如果当前的选择费用超出了M,就pop出堆里的最大的,一直到不超过M为止。咋维护呢,好像有个东西叫左偏树来着QAQQQQ
    动态维护当前选择的节点数num和选择费用sum即可。

    代码

    #include<cstdio>
    #include<algorithm> 
    using std::swap;
    inline int read() {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar(); }
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f;
    } 
    #define int long long
    int n,m; 
    const int maxn = 200007; 
    int c[maxn],b[maxn],l[maxn];  
    int num = 0,head[maxn]; 
    struct node { 
        int v,next; 
    }edge[maxn << 1]; 
    void add_edge(int u ,int v) {
        edge[++num].v = v,edge[num].next = head[u],head[u] = num; 
    } 
    struct Leftist_Tree {
        int lc,rc,dis,val; 
        bool operator < (const Leftist_Tree &q) const {
            return val > q.val; 
        }  
    } t[maxn];  
    int fa[maxn]; 
    #define lc t[x].lc 
    #define rc t[x].rc 
    int merge(int x,int y) { 
        if(!x || !y) return x + y;  
        if(t[y] < t[x]) swap(x,y);  
        if(t[y].val == t[x].val && x > y) swap(x,y);  
        fa[rc = merge(rc,y)] = x;  
        if(t[lc].dis < t[rc].dis) swap(lc,rc);  
        t[x].dis = t[rc].dis + 1;  
        return x ;  
    } 
    int pop(int x) { 
        fa[lc] = fa[rc] = 0; 
        int ret = merge(lc,rc); 
        lc = rc = 0; 
        return ret; 
    } 
    #undef lc 
    #undef rc  
    int sum[maxn],size[maxn],root[maxn],ans;  
    
    void dfs(int u) { 
        root[u] = ++num; 
        t[num].val = c[u]; 
        size[u] = 1;sum[u] = c[u]; 
        for(int i = head[u]; i;i = edge[i].next) { 
            int v = edge[i].v; 
            dfs(v); 
            sum[u] += sum[v]; 
            size[u] += size[v]; 
            root[u] = merge(root[u],root[v]); 
        }  
        while(sum[u] > m)  { 
            sum[u] -= t[root[u]].val; 
            root[u] = pop(root[u]); 
            size[u] --; 
        } 
        ans = std::max(ans,l[u] * size[u]); 
        return ; 
    } 
    main() { 
        n = read(),m = read() ; 
        t[0].dis = -1;
        int rt = 0; 
        for(int i = 1;i <= n;++ i) { 
            b[i] = read(), c[i] = read(),l[i] = read(); 
            if(b[i]) add_edge(b[i],i); 
            else rt = i; 
        } 
        num  = 0; 
        dfs(rt); 
        printf("%lld
    ",ans); 
        return 0;
    }
    
  • 相关阅读:
    RSA 与 DSA
    atlassian
    Cygwin
    windows下编写的Shell脚本在Linux下运行错误的解决方法
    NSKeyValueObserving(KVO)
    UIBezierPath 的使用介绍
    Objective
    Objective-C 内存管理原则
    Mac OSX 快捷键&命令行总览
    浅析Objective-C字面量
  • 原文地址:https://www.cnblogs.com/sssy/p/8996308.html
Copyright © 2011-2022 走看看