zoukankan      html  css  js  c++  java
  • [题解] [APIO2012] 派遣

    题面

    题解

    很显然的思路就是对于每一个点分开计算他对答案的贡献

    这样会造成贡献的便只有他子树内的点了

    贪心地选择最小的直到他们的和 $ > m$

    现在问题在于怎么求子树内的这个东西, 并且如何合并

    可以可并堆, 也可以 splay 启发式合并(我已开始想写, 以为启发式合并很难想, 结果最后就是一个小的接到大的上面)

    这里采用的是另一种方法

    根据 DFS 序建立主席树, 这样一个子树内的 DFS 序是连续一段, 直接查就行了

    不懂为什么有些人还要加一个二分

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    typedef long long ll; 
    const int N = 100005; 
    using namespace std; 
    
    int n, m, head[N], cnt, pre[N], dfn[N], sz[N], w[N], up[N], root, rt[N]; 
    struct edge { int to, nxt; } e[N];
    struct Tree { int sz, l, r; ll sum; } t[N * 60];
    ll ans; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    inline void adde(int u, int v) { e[++cnt] = (edge) { v, head[u] }, head[u] = cnt; }
    
    void dfs(int u)
    {
    	pre[dfn[u] = ++cnt] = u, sz[u] = 1;
    	for(int i = head[u]; i; i = e[i].nxt)
    		dfs(e[i].to), sz[u] += sz[e[i].to]; 
    }
    
    void modify(int &p, int o, int l, int r, int x)
    {
    	p = ++cnt, t[p] = t[o], t[p].sz++, t[p].sum += x;
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(x <= mid) modify(t[p].l, t[o].l, l, mid, x);
    	else modify(t[p].r, t[o].r, mid + 1, r, x); 
    }
    
    int query(int p, int o, int l, int r, int sum, int res)
    {
    	if(l == r)
    	{
    		res += min(sum / l, t[p].sz - t[o].sz); 
    		return res; 
    	}
    	int mid = (l + r) >> 1; ll lsum = t[t[p].l].sum - t[t[o].l].sum; 
    	if(lsum >= sum) return query(t[p].l, t[o].l, l, mid, sum, res);
    	else return query(t[p].r, t[o].r, mid + 1, r, sum - lsum, res + t[t[p].l].sz - t[t[o].l].sz); 
    }
    
    int main()
    {
    	n = read <int> (), m = read <int> ();
    	for(int x, i = 1; i <= n; i++)
    	{
    		x = read <int> (), w[i] = read <int> (), up[i] = read <int> ();
    		if(!x) root = i;
    		else adde(x, i); 
    	}
    	cnt = 0, dfs(root), rt[0] = (cnt = 1); 
    	for(int i = 1; i <= n; i++)
    		modify(rt[i], rt[i - 1], 1, m, w[pre[i]]);
    	for(int i = 1; i <= n; i++)
    		ans = max(ans, 1ll * up[i] * query(rt[dfn[i] + sz[i] - 1], rt[dfn[i] - 1], 1, m, m, 0)); 
    	printf("%lld
    ", ans); 
    	return 0; 
    }
    
  • 相关阅读:
    Struts学习之手动验证
    Struts学习之文件上传
    Struts学习之模型驱动
    Struts学习之类型转换
    Struts学习之自定义拦截器
    Java基础之"=="和 和 equals 方法的区别
    Hadoop学习之Hadoop案例分析
    Hadoop学习之Hadoop集群搭建
    Hadoop学习之自定义二次排序
    Hadoop学习之Mapreduce执行过程详解
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12187889.html
Copyright © 2011-2022 走看看