bzoj 2809

将薪水离散化
建立主席树
主席树的下标为离散后薪水
枚举每一个节点当作领导者
Answer取max

代码有点啰嗦

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>

using namespace std;
const int N = 1e5 + 10, N_ = N * 25;

#define gc getchar()
#define LL long long

LL n, m, now = 1, Tjs, cnt, js;
LL head[N];
struct Node {LL v, nxt;} G[N << 1];
struct Node_2 {LL Tree_, C_, L_, C_dispersed; /*离散后的值 */} Use[N];
LL Root[N], Lst[N], Rst[N], Tree[N];
LL C[N], L[N];
LL Peo[N_], W[N_], Lson[N_], Rson[N_];

inline LL read() {
    LL x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
} 

inline void Add(LL u, LL v) {G[now].v = v; G[now].nxt = head[u]; head[u] = now ++;}
inline bool cmp(Node_2 a, Node_2 b) {return a.Tree_ < b.Tree_;}
inline bool cmp_1(Node_2 a, Node_2 b) {return a.C_ < b.C_;} 

void Dfs(LL u, LL fa) {
    Tree[u] = ++ Tjs;
    Lst[u] = Tjs;
    bool flag = 1;
    for(int i = head[u]; ~ i; i = G[i].nxt) {
        flag = 0;
        int v = G[i].v;
        if(v != fa) Dfs(v, u);
    }
    if(flag) return ;
    Rst[u] = Tjs;
}

void Fill(LL x, LL y) {Peo[x] = Peo[y], W[x] = W[y], Lson[x] = Lson[y], Rson[x] = Rson[y];}

void Build_tree(LL &rt, LL x, LL l, LL r, LL ture_c) {
    Fill(++ cnt, rt);
    rt = cnt;
    W[rt] += ture_c, Peo[rt] ++;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    if(x <= mid) Build_tree(Lson[rt], x, l, mid, ture_c);
    else Build_tree(Rson[rt], x, mid + 1, r, ture_c);
}

map <LL, LL> Map, Map2;

int Now_ans;

void Ask(LL lrt, LL rrt, LL l, LL r, LL Now_c) {
    LL delc = W[Lson[rrt]] - W[Lson[lrt]], delpeo = Peo[Lson[rrt]] - Peo[Lson[lrt]];
    int mid = (l + r) >> 1;
    if(l == r) {
        Now_ans += min(Now_c / Map[l], Peo[rrt] - Peo[lrt]);
        return ;
    }
    if(Now_c >= delc) {
        Now_ans += delpeo;
        Ask(Rson[lrt], Rson[rrt], mid + 1, r, Now_c - delc);
    } else Ask(Lson[lrt], Lson[rrt], l, mid, Now_c);
}

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; i ++) head[i] = -1;
    for(int i = 1; i <= n; i ++) {
        int v = read();
        C[i] = read(), L[i] = read();
        if(i != 1) Add(i, v), Add(v, i);
    }
    Dfs(1, 0);
    for(int i = 1; i <= n; i ++) 
        Use[i].Tree_ = Tree[i], Use[i].L_ = L[i], Use[i].C_ = C[i];
    std:: sort(Use + 1, Use + n + 1, cmp_1);
    js = 1; Use[1].C_dispersed = 1;
    // 薪水 
    for(int i = 2; i <= n; i ++) {
        if(Use[i].C_ != Use[i - 1].C_) Use[i].C_dispersed = ++ js;
        else Use[i].C_dispersed = js;
    }
    // dfs 序 
    for(int i = 1; i <= n; i ++) Map[Use[i].C_dispersed] = Use[i].C_;
    // 按照 dfs 序的大小插入 
    std:: sort(Use + 1, Use + n + 1, cmp);
    for(int i = 1; i <= n; i ++) {
        Root[i] = Root[i - 1];
        Build_tree(Root[i], Use[i].C_dispersed, 1, js, Use[i].C_);
    } 
    LL Answer = 0;
    for(int i = 1; i <= n; i ++) { // 以 i 节点为领导者 
        Now_ans = 0;
        Ask(Root[Lst[i] - 1], Root[Rst[i]], 1, js, m);
        Answer = max(Answer, 1ll * Now_ans * L[i]);
    }
    cout << Answer;
    return 0;
}

 

posted @ 2018-06-27 17:20  qmey  阅读(92)  评论(0编辑  收藏  举报