传送门: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; }