[题解] [JSOI2015] 套娃

题面

题解

首先假设每个娃都不套, 那么代价就是 \(\sum_{i=1}^{n}b_i*in_i\)

然后每次将 \(j\) 套进 \(i\) 中会减去 \(b_i*out_j\) 的代价

发现将 \(b\) 排序后拿个数据结构维护一下最大的小于等于当前的 \(in_i\)\(out_j\)

证明直接拿两个套娃, 保证可以都套进另外两个套娃, 若不是按照这种决策可以发现不会更优

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <set>
typedef long long ll; 
const int N = 2e5 + 5; 
using namespace std; 

int n; 
struct node
{
    int out, in, b; 
    bool operator < (const node &p) const
    {
        return b > p.b; 
    }
} q[N]; 
ll ans; 
multiset<int> s; 
multiset<int> :: iterator it; 

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; 
}

int main()
{
    n = read <int> (); 
    for(int i = 1; i <= n; i++)
    {
        q[i].out = read <int> (), q[i].in = read <int> (), q[i].b = read <int> (); 
        ans += 1ll * q[i].b * q[i].in, s.insert(q[i].out); 
    }
    sort(q + 1, q + n + 1); 
    for(int i = 1; i <= n; i++)
    {
        it = s.lower_bound(q[i].in); 
        if(it == s.end()) continue; 
        if(it != s.begin())
            it--, ans -= 1ll * q[i].b * (*it), s.erase(it); 
    }
    printf("%lld\n", ans); 
    return 0;   
}
posted @ 2020-02-24 20:45  ztlztl  阅读(175)  评论(0编辑  收藏  举报