某岛

… : "…アッカリ~ン . .. . " .. .
January 16, 2013

BZOJ 2809: [Apio2012]dispatching

Brief description:

。。给定一颗 N 个节点的树,总资金 M。。。对每个节点有两个参数 C_u(代价), L_u(收益因子)。。
。。对于一颗以 u 为根的子树。。你可以选择一组点集 S。。使得点集的代价和不超过 M。。则带来的收益是 L_u |S|。。
。。最大化收益。。。

Analysis:

算法一:平衡树启发式合并
。。贪心,对于每个点为根的子树,我们需要知道其子树中,前 k 小的结点分别是多少。。
那么最普通的做法是平衡树启发式合并。。

https://gist.github.com/lychees/ed2b51f66fa60305ac8d

算法二:暴力 + 路径压缩

然后这个题有一种很碉堡的暴力算法。。用路径压缩优化。。
(虽然最坏情况下还是会退化成 O(n2)。 m 特别大。。使得路径压缩不会发生。。。。但是居然可以 AC?)
(路径压缩。。3400ms+

/}/* .................................................................................................................................. */

const int N = int(1e5) + 9;

int p[N], c[N], l[N], o[N], s[N]; LL f[N];
int n; LL m, ans;

void gao(int x){
    int r = c[x];
    while (x){
        if (r + f[x] <= m) f[x] += r, ++s[x];
        else p[x] = p[p[x]];
        x = p[x];
    }
}

bool cmp(int a, int b){
    return c[a] < c[b];
}

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif

    RD(n, m); REP_1(i, n) RD(p[i], c[i], l[i]), o[i] = i;
    sort(o+1, o+1+n, cmp); REP_1(i, n) gao(o[i]);
    REP_1(i, n) checkMax(ans, (LL) l[i] * s[i]);
    OT(ans);
}

算法三:左偏树?
http://www.cnblogs.com/jianglangcaijin/p/3458158.html
算法四:主席树
http://hi.baidu.com/greencloud/item/a0f0903b2148bfcb2e8ec2d3

External link:

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