题意:
Alice 和 Bonnie在玩一个游戏,规则如下:
有n个栈,每个栈里有两张照片,每张照片有两个属性ai和bi,含义是,如果Alice拿了这张照片,那么她获得ai分数,如果Bonnie拿到这张照片那么她获得bi分数,以下简称Alice为A,Bonnie为B
这个游戏的最终目的,并不是要想办法让自己的分数最大,而是让自己的分数与对手分数的差值尽可能大。
当然,因为照片是放在栈里的所以只有当栈顶的那张照片被拿走后,才能拿栈底的那张照片
现在由A先手,AB轮流操作,每次可以选择任意拿走一张照片(前提是拿得到)或者不执行任何操作,游戏结束,当所有照片被拿完或是双方连续不操作。问在规则下,A得到的分数-B得到的分数的最大值是多少?
solution:
对同一个栈内的两张照片分析
不妨用四个数字a,b,c,d表示一个栈,代表第一张照片能给A贡献a分,B贡献b分,c,d类似
若a + b >= c + d,这时,无论双方谁先拿了这个栈栈顶的照片,谁都不会让自己的局势更劣
因为a - d >= b - c或是b - c >= d - a
但是如果反过来,a + b < c + d,难道AB都不愿意先手?
事实上,若a > d,因为a - d < c - b,虽然A先手拿这个栈的照片得到的收益不如后手,但是至少对自己的局势有所贡献,另一方面,这时候b - c < d - a < 0,如果B先手,承受的扣分会更严重一些,所以B绝对不会在这个栈先手。因此这个栈等价于一张价值(a-d,d-a)的照片,总是会被记入答案
同理,当b > c,这个栈等价于一张价值(c-b,b-c)的照片,且一定会被记入答案
如果上述两种情况都不发生,无论谁在这个栈先手,另一方总能通过马上在这个栈拿走栈底照片,让自己的局势更优,因此,谁都不会在这样的栈做任何操作
这样,就剩下那些a + b >= c + d的照片了,既然谁都希望在这样的栈先手,那当然是每次取价值最大的照片了
不过这个价值是考虑双方面的,把一张(a,b)的照片替换成(a+b,a+b),然后答案加上a-b
A取这张照片,a+b+a-b = 2a,B取这张照片,a-b-a-b = -2b
那么也就能维护了,开个堆或者排序一下,每次取最大
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E5 + 10;
typedef long long LL;
int n;
LL ans;
priority_queue <LL> Q;
void Add(int x,int y)
{
ans += 1LL*(x-y);
Q.push(x+y);
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (int i = 1; i <= n; i++) {
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if (a + b >= c + d) Add(a,b),Add(c,d);
else if (a > d) ans += 2LL*(a-d);
else if (b > c) ans += 2LL*(c-b);
}
LL cur = 1;
while (!Q.empty()) {
ans += cur*Q.top();
Q.pop(); cur *= -1;
}
cout << ans/2LL;
return 0;
}