题目传送门
分析
和国王游戏一样的思路直接考虑邻项交换
观察易知排在后面的大臣获得的奖赏一定更多
假设前 \(i - 1\) 位左手上的数和为\(a\),第 \(i - 1\) 位获得奖赏为\(c_{i - 1}\);
对于排在第 \(i\) 位和第 \(i + 1\) 位的大臣,
交换前,最大收益
交换后,最大收益
\[w2 = max(max(c_{i-1},\sum_{j=1}^{i-1}a_j+a_{i+1})+b_{i+1},\sum_{j=1}^{i+1}a_j)+b_i=…… \\=max(c_{i-1}+b_i+b_{i+1},\sum_{j=1}^{i-1}a_j+a_{i+1}+b_i+b_{i+1},\sum_{j=1}^{i+1}a_j+b_{i}) \]为了使交换前收益最小需要满足 \(w1 < w2\) ,则有
\[max(\sum_{j=1}^ia_j+b_i+b_{i+1},\sum_{j=1}^{i+1}a_j+b_{i+1})<max(\sum_{j=1}^{i-1}a_j+a_{i+1}+b_i+b_{i+1},\sum_{j=1}^{i+1}a_j+b_{i})\\max(a_i+b_i+b_{i+1},a_i+a_{i+1}+b_{i+1})<max(b_i+b_{i+1}+a_{i+1},a_i+b_i+a_{i+1})\\max(b_i,a_{i+1})+a_i+b_{i+1}<max(b_{i+1},a_i)+b_i+a_{i+1}\\max(-a_{i+1},-b_i)<max(-a_i,-b_{i+1})\\min(a_{i+1},b_i)>min(a_i,b_{i+1})\\min(a_i,b_{i+1})<min(a_{i+1},b_i) \]所以只需要按这个规定贪心排序即可,个人认为传递性是存在的,手推了一下满足条件的所有情况,都没有矛盾(就是懒得用反证法)
但是没有考虑的是当 \(min(a_i,b_{i+1})=min(a_{i+1},b_i)\) 时应该如何排序
在一个相对的平衡里,如果我的某一方面属性在局面里有较大作用(比方说右手数字比你大,因为计算时最后直接加的右手数字)那么把我排在你前面才能使答案缩小,所以在这个平衡状态里我选择把右手数字大的排在前面。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define rg register
inline int read(){
rg int x = 0, f = 1;
rg char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * f;
}
const int N = 2e4 + 1;
struct minister{
int l, r;
bool operator <(minister b) const{
if (min(l, b.r) == min(r, b.l))
return l < b.l;
return min(l, b.r) < min(r, b.l);
}
/*int l, r, d;
bool operator < (minister b) const{
if (d != b.d) return d < b.d;
if (d < 0) return l < b.l;
else return r > b.r;
}*/
}a[N];
int n;
long long sum;
long long c[N];
inline void init(){
n = read();
for (int i(1); i <= n; ++i){
a[i].l = read(), a[i].r = read();
/* if (a[i].l > a[i].r) a[i].d = 1;
else if (a[i].l < a[i].r) a[i].d = -1;
else a[i].d = 0;*/
}
sum = 0;
}
inline void doit(){
sort(a + 1, a + 1 + n);
for (int i(1); i <= n; ++i){
sum += a[i].l;
c[i] = max(c[i - 1], sum) + a[i].r;
}
printf("%lld\n", c[n]);
}
int main(){
ios::sync_with_stdio(false);
cout.tie(NULL);
int T = read();
while (T--){
init();
doit();
}
return 0;
}
标签:游戏,min,int,luogu,sum,long,P2123,max,include
From: https://www.cnblogs.com/cancers/p/17038663.html