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; }