zoukankan      html  css  js  c++  java
  • 洛谷 [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;
    }
    
  • 相关阅读:
    前端常见跨域解决方案
    VS单元测试--初级篇
    高等数学思路
    二元函数求极值判别式AC-B^2
    向量积详解
    伯努利分布均值和方差
    两个标准正态随机变量相乘的方差
    a分位数与双侧a分位数
    中心极限定理概念理解与记忆
    样本方差概念解析
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8964527.html
Copyright © 2011-2022 走看看