洛谷 [P1552] 派遣

树型DP + 可并堆

非常清楚的想到是树型DP, 但是如何维护最小值, 于是就去新学了可并堆

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
const int MAXN = 100005;
ll init() {
	ll rv = 0, fh = 1;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') fh = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		rv = (rv<<1) + (rv<<3) + c - '0';
		c = getchar();
	}
	return fh * rv;
}
struct edge{
	int to, nxt;
}e[MAXN << 1];
int n, m, head[MAXN], nume, rot, fa[MAXN], id[MAXN];
ll ans, wei[MAXN], mon[MAXN], siz[MAXN], sum[MAXN]; 
void adde(int from, int to) {
	e[++nume].to = to;
	e[nume].nxt = head[from];
	head[from] = nume;
}
struct LT{
	struct node{
		int l, r;
		ll val, dist;
	}a[MAXN];
	int merge(int u, int v) {
		if(!u || !v) return u + v;
		if(a[u].val < a[v].val) swap(u, v);
		int &ur = a[u].r, &ul = a[u].l;
		ur = merge(ur, v);
		if(a[ul].dist < a[ur].dist) swap(ul, ur);
		a[u].dist = a[ur].dist + 1;
		return u;
	}
	void erase(int &u) {
		u = merge(a[u].l, a[u].r);
	}
}lt;
void dfs(int u) {
	id[u] = u;
	siz[u] = 1;
	sum[u] = mon[u];
	lt.a[u].val = mon[u];
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		dfs(v);
		sum[u] += sum[v];
		siz[u] += siz[v];
		id[u] = lt.merge(id[u], id[v]);
	}
	while(sum[u] > m && siz[u]) {
		siz[u]--;
		sum[u] -= lt.a[id[u]].val;
		lt.erase(id[u]);
	}
	ans = max(ans, siz[u] * wei[u]);
}
int main() {
	n = init(); m = init();
	for(int i = 1; i <= n; i++) {
		fa[i] = init();
		if(fa[i]) adde(fa[i], i);
		else rot = i;
		mon[i] = init(); wei[i] = init();
	}
	dfs(rot);
	/*for(int i = 1; i <= n; i++) {
		printf("%lld %lld
", siz[i], sum[i]);
	}*/
	cout << ans << endl;
	return 0;
}
原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8964527.html