agc026F Manju Game
-
从左到右有 n n n个物品,每一个价值为 a i a_i ai。
-
现在A和B轮流取物品。
-
不妨假设现在先手的人是A,他可以任意取一个,假设是 x x x,后手的人可以取任意一个与 x x x相邻的物品,如果取 x + 1 x+1 x+1,那么将轮流往右取直到没有,反之取 x − 1 x-1 x−1将轮流往左取直到没有。
-
取完一个物品之后重标号。
-
一开始A先手,A、B都想让自己取的物品最大,求他们在最优策略下最后各获得多大的价值。
-
n ≤ 3 e 5 , a i ≤ 1 e 3 n\le3e5,a_i\le1e3 n≤3e5,ai≤1e3
Solution
- 神奇的博弈题,需要深入思考先手和后手的策略,以及先后手的转换。
- 先手要发挥主观能动性,后手要尽可能获得先手权,由于确定方向之后选择是固定的,我们可以从先手的选择讨论是否会交换先手权。
-
n
n
n为偶数:
- 显然A可以直接选开头或结尾,取走奇数位置或偶数位置的物品。
- 注意到如果A选择中间的某一个,一定有一边剩下偶数个,B可以借此机会获得先手权,因为B如果把先手权让出去,另一边与A的安排一样,之后又继续在A的掌控之下了,所以B获得先手权能让偶数个那边在A安排下,另一边不比原先劣(先手的优势)。
- 那么但凡A选择中间的,B获得先手,就比A的安排下(只直接选择头或尾)不劣,A不想看到这种情况。
- 得出结论,A一定选头或尾。
-
n
n
n为奇数:
- A选择了奇数位:
- 类似上面的情况,如果不选择头或尾,会交出先手权,使得选择位置有一边在A的安排下,另一边失去控制,B的选择会更优。
- 因此A一定选择头或尾。
- A选择了偶数位:
- 不管B选择左边还是右边,先手权始终在A的手上。
- 但是A选择中间的某个位置之后,B可以选择把接下来的局面往左侧或右侧引导,最终到某个时候剩下一个奇数区间,A发现很有利的时候直接走奇数位——选择头或尾。
- 单独考虑A的选择,我们选若干个偶数位置,B只能决定左右,但是A能决定端点,假设B知道了A的决策——即选出的位置,肯定会往最终对B最有利的区间引导,所以A想让B引导到的最小值还是最大的。
- 因此问题转化为了选择若干个偶数位置,使得每个相邻区间对A的好处的最小值最大(我们将好处定义为“A贡献”-“B贡献”)。
- 直接二分,贪心判定即可。
- A选择了奇数位:
- 至此可以在 O ( n l o g w ) O(n\ log \ w) O(n log w)内解决。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define maxn 300005
using namespace std;
int n,i,j,k,a[maxn],s[maxn];
int check(int mid){
int mi=0;
for(i=1;i<=n/2+1;i++) if (s[i]+a[i*2]-mi>=mid)
mi=min(mi,s[i]);
else if (i==n/2+1) return 0;
return 1;
}
int main(){
freopen("ceshi.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
if (n&1){
for(i=1;i<=n/2+1;i++) s[i]=s[i-1]+a[2*i-1]-a[2*i];
int l=-1e9,r=1e9,mid,ans=-1e9;
while (l<=r){
mid=(l+r)>>1;
if (check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
int sum=-s[n/2+1]+ans*2,s0=0;
for(i=1;i<=n;i++) s0+=a[i];
printf("%d %d\n",(sum+s0)/2,(s0-sum)/2);
} else {
int s1=0,s2=0;
for(i=1;i<=n;i+=2) s1+=a[i],s2+=a[i+1];
if (s1<s2) swap(s1,s2);
printf("%d %d\n",s1,s2);
}
}