bzoj2809 可并堆(左偏树)
题意:给你一颗树,每个节点有2个权值,li表示该点的领导力,ci表示花费,选择一个子树,该子树的根作为领导,然后从这个子树下选出x个节点,所有选出的节点的花费和不大于m,得到一个价值为 领导力乘选出的节点数, 即ans=li*x,求最大值
思路:首先可以知道的是当选出了一个子树时,只要贪心得在这颗子树下每次取出花费最小的即可,直到总花费大于m,即可以dfs每次选出一个子树,先将所有点选取,然后每次删除花费最大的节点,直到总花费不大于m,用可并堆维护即可
AC代码:
#include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define step(x) fixed<< setprecision(x)<< #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ll long long #define endl ("\n") #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll mod=1e9+7; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const double PI=acos(-1.0); const int N=1e5+100; int rt[N], ls[N], rs[N], d[N], siz[N], val[N], cnt = 0; int head[N], to[N], nex[N], li[N], tot; int n, M; ll ans, sum[N]; void add(int u, int v) { to[tot] = v; nex[tot] = head[u]; head[u] = tot++; } void updata(int x) { siz[x] = siz[ls[x]]+siz[rs[x]]+1; sum[x] = sum[ls[x]]+sum[rs[x]]+val[x]; if(d[ls[x]] < d[rs[x]]) swap(ls[x], rs[x]); if(!rs[x]) d[x] = 0; else d[x] = d[rs[x]] + 1; } int Merge(int x, int y) { if(!x || !y) return x+y; if(val[x] < val[y]) swap(x, y); rs[x] = Merge(y, rs[x]); updata(x); return x; } void pop(int &x) { int last = x; x = Merge(ls[x], rs[x]); ls[last] = rs[last] = d[last] = 0; } void dfs(int u) { rt[u] = u, siz[u] = 1, sum[u] = val[u]; for(int i=head[u]; i!=-1; i=nex[i]) { int v = to[i]; dfs(v); rt[u] = Merge(rt[u], rt[v]); } while(siz[rt[u]] && sum[rt[u]] > M) pop(rt[u]); ans = max(ans, (ll)siz[rt[u]]*(ll)li[u]); } int main(){ scanf("%d %d", &n, &M); mem(head, -1); int root = 0; for(int i=1; i<=n; ++i) { int b, c, l; scanf("%d %d %d", &b, &c, &l); val[i] = c, li[i] = l; add(b, i); if(b == 0) root = i; } dfs(root); printf("%lld\n", ans); return 0; }