AIsing Programming Contest 2020 E

题目

题目意思很贪心,但有些放左边好,有些放右边好,一起做不好弄

可以分开做:一定存在一种最优方案,使得所有放在左边更优的都在左侧(存在一个分界点)

然后把两个种类分开贪心,以左边的为例:

用一个set存储还没放的位置

将所有camels按照Ri-Li排序,从大的开始处理,如果能放,就放在能放的最靠右的位置,否则直接放在最右侧

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
void read (int &x) {
    char ch = getchar(); x = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
} const int N = 2e5 + 10;
int n, k[N], l[N], r[N];
pair<int, int> p[N];
#define x first
#define y second
set<int> s;
vector<pair<int, int> > va, vb;
signed main() {
    int T; read (T);
    while (T--) {
        read (n); long long res = 0;
        va.clear(), vb.clear();
        for (int i = 1; i <= n; ++i) {
            read (k[i]), read (l[i]), read (r[i]);
            if (l[i] >= r[i])
                res += r[i], va.push_back (make_pair(l[i] - r[i], k[i]));
            else res += l[i], vb.push_back (make_pair(r[i] - l[i], n - k[i]));
        }
        s.clear(); sort (va.begin(), va.end());
        for (int i = 1; i <= va.size(); ++i) s.insert (i);
        set<int>::iterator it;
        for (int i = va.size() - 1; i >= 0; --i) {
            it = s.upper_bound (va[i].y);
            if (it == s.begin()) it = s.end(), --it, s.erase (it);
            else --it, s.erase (it), res += va[i].x;
        }
        s.clear(); sort (vb.begin(), vb.end());
        for (int i = 1; i <= vb.size(); ++i) s.insert (i);
        for (int i = vb.size() - 1; i >= 0; --i) {
            it = s.upper_bound (vb[i].y);
            if (it == s.begin()) it = s.end(), --it, s.erase (it);
            else --it, s.erase (it), res += vb[i].x;
        } printf ("%lld
", res);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/whx666/p/13359979.html