为了能到远方,脚下的每一步都不能少.|

luckydrawbox

园龄:4个月粉丝:1关注:2

P8002 Alice and Bob are playing a Normal Game

Link\text{Link}

题意

一开始有一个序列 a1,a2,,ana_1,a_2,…,a_n,记此时的 ansansi=1n(1)i1ai\sum_{i=1}^n(-1)^{i-1}a_i,接下来有一个公开的非负整数操作序列 x1,x2,,xkx_1,x_2,…,x_k,即 Alice 和 Bob 都知道。

接下来 Alice 和 Bob 交替操作一共 kk 次,Alice 先,第 ii 次操作为使 ansans 变为 p±ans(xipxi)p\pm ans(-x_i\le p\le x_i)

Alice 希望最后的 ansans 最大,而 Bob 希望最后的 ansans 最小,在两人都采取最优策略的情况下,求出最后的 ansans

分析

乍一看好像是 Alpha-Beta\text{Alpha-Beta} 剪枝,然而 1n,k2×105,0ai,xi1091≤n,k≤2×10^5 ,0\le |a_i|,x_i\le 10^9 的范围是过不了的。


于是我们考虑自己当一回 Alice & Bob 精神分裂

Round 1   k=1\text{Round 1 \ \ }k=1

  • Alice:天助我也,Bob 什么都做不了,我只要使答案最大就可以了,ansx1+ansans\Longleftarrow x_1+\left|ans\right|

Round 2   k=2\text{Round 2 \ \ }k=2

  • Alice:最后一次操作是 Bob 执行的,不论我这轮操作后 ansans 的大小如何,Bob 都可以通过 ansx2ansans\Longleftarrow -x_2-\left|ans\right| 使最后的结果尽可能小,既然这样,我只要使 ans\left|ans\right| 尽可能小就可以了,如果 ansx1\left|ans\right|\le x_1,显然可以使它变为 00,否则最小只能变成 ansx1\left|ans\right|-x_1 了。
  • Bob:我现在掌握着最后一轮的结果,要使答案尽可能小, 只要 ansx2ansans\Longleftarrow -x_2-\left|ans\right|,无论如何答案都是最小的。

Round 3   k=3\text{Round 3 \ \ }k=3

  • Alice:最后一次操作是我执行的,那是我会使 ansx3+ansans\Longleftarrow x_3+\left|ans\right|,所以我只要使 ans\left|ans\right| 尽可能大就好了,ansx1+ansans\Longleftarrow x_1+\left|ans\right|
  • Bob:局势对 Alice 十分有利,她最后得到的答案与 ans\left|ans\right| 有关,所以我还是要使其尽可能小,如果 ansx2\left|ans\right|\le x_2,显然可以使它变为 00,否则最小只能变成 ansx2\left|ans\right|-x_2 了。
  • Alice:该做什么就显而易见了,ansx3+ansans\Longleftarrow x_3+\left|ans\right|

不难发现,Alice 和 Bob 所做的举动和 kk 的奇偶性有关:

  • kmod2=1k\bmod 2=1:Alice 每次使 ans\left|ans\right| 最大,Bob 每次使 ans\left|ans\right| 最小。
  • kmod2=0k\bmod 2=0:Alice 每次使 ans\left|ans\right| 最小,Bob 每次使 ans\left|ans\right| 最大。

于是按题意模拟即可,时间复杂度 O(n+k)O(n+k),空间复杂度 O(1)O(1)

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int N=2e5+10;
int n,k;
ll ans,x;
ll minabs(ll a,ll b){//ans绝对值的最小值
	if(abs(a)<=b)
		return 0;
	return abs(a)-b;
}
int main(){
	n=read();k=read();
	for(int i=1;i<=n;i++)
		ans+=(read()*(i%2?1:-1));
	if(k%2)
		for(int i=1;i<=k;i++){
			x=read();
			if(i%2)
				ans=x+abs(ans);
			else
				ans=minabs(ans,x);
		}
	else
		for(int i=1;i<=k;i++){
			x=read();
			if(i%2)
				ans=minabs(ans,x);
			else
				ans=-x-abs(ans);
		}
	write(ans);
	return 0;
}

本文作者:luckydrawbox

本文链接:https://www.cnblogs.com/luckydrawbox/p/18526568

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   luckydrawbox  阅读(5)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起