bzoj2809 [Apio2012]dispatching

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2809

【题解】

枚举选定的领导者,从领导者下属选择一坨他们的薪水<=m,那么肯定贪心选。

下面一坨选可以用主席树,为了使他们连起来,用DFS序。。

我真是傻逼dfs序都会写错。。

# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, C, cap;
int c[M], L[M];

int head[M], nxt[M], to[M], tot=0;
inline void add(int u, int v) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}
inline void adde(int u, int v) {
    add(u, v); add(v, u);
}

int in[M], out[M], DFN=0, dfn[M];
inline void dfs(int x, int fa) {
    in[x] = ++DFN; dfn[DFN] = x;
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], x);
    }
    out[x] = DFN;
}

int rt[M];
namespace CMT {
    const int M = 5e6 + 10;
    ll s[M];
    int ch[M][2], siz, sz[M];
    inline void edt(int &x, int y, int l, int r, int pos) {
        x = ++siz; ch[x][0] = ch[y][0], ch[x][1] = ch[y][1];
        s[x] = s[y] + pos; sz[x] = sz[y] + 1;
        if(l == r) return;
        int mid = l+r>>1;
        if(pos <= mid) edt(ch[x][0], ch[y][0], l, mid, pos);
        else edt(ch[x][1], ch[y][1], mid+1, r, pos);
    }
    inline ll query(int x, int y, int l, int r, ll res) {
        if(res<l) return 0;
        if(l == r) return min(res/l, (ll)sz[y]-sz[x]);
        ll le = s[ch[y][0]] - s[ch[x][0]];
        int mid = l+r>>1;
        if(le <= res) return (ll)sz[ch[y][0]] - sz[ch[x][0]] + query(ch[x][1], ch[y][1], mid+1, r, res-le);
        else return query(ch[x][0], ch[y][0], l, mid, res);
    }
}

int main() {
    scanf("%d%d", &n, &C);
    for (int i=1, u; i<=n; ++i) {
        scanf("%d%d%d", &u, c+i, L+i);
        if(u) adde(u, i);
        else cap = i;
    }
    dfs(cap, 0);
    for (int i=1; i<=n; ++i) 
        CMT::edt(rt[i], rt[i-1], 1, 1e9, c[dfn[i]]);
    ll ans = 0;
    int ps;
    for (int i=1; i<=n; ++i) {
        ll t = L[i];
        t = t * CMT::query(rt[in[i]-1], rt[out[i]], 1, 1e9, C);
        if(t > ans) {
            ans = t;
            ps = i;
        }
    }
    printf("%lld
", ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/galaxies/p/bzoj2809.html