题目意思很贪心,但有些放左边好,有些放右边好,一起做不好弄
可以分开做:一定存在一种最优方案,使得所有放在左边更优的都在左侧(存在一个分界点)
然后把两个种类分开贪心,以左边的为例:
用一个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;
}