CF1555C Coin Rows题解--zhengjun

题目大意

有一个 \(2\times m\) 的矩阵,每次从 \((1,1)\) 号点,往下或往右走到 \((2,m)\)。Alice 先出发,把经过的点上的权值清空,然后 Bob 再出发,把经过的点上的权值加起来作为答案。Alice 希望最小化答案,Bob 希望最大化答案,求最后的答案。

思路

首先,从 \((1,1)\) 走到 \((2,m)\) 的路径条数也不过就 \(m\) 条,考虑枚举 Alice 走的路径(枚举从哪一列往下走),然后注意到 \(a_{i,j}\ge1\),所以 Bob 一定是选得越多越好,那么 Bob 要么到了 \((1,m)\) 再往下走,要么在 \((1,1)\) 就往下走,这样答案最大。

这样就可以发现,Bob 最后拿到分数的点要么是第一行的一段后缀,要么是第二行的一段前缀,所以预处理第一行的后缀和以及第二行的前缀和,枚举 Alice 走的路径,计算答案就可以了。

每次注意把后缀和以及前缀和的数组清空,不然会影响之后的答案。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
void read(){}
template<typename _Tp,typename... _Tps>
void read(_Tp &x,_Tps &...Ar){
	x=0;char c=getchar();bool flag=0;
	while(c<'0'||c>'9')flag|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
	if(flag)x=-x;
	read(Ar...);
}
const int N=1e5+10;
int n,a[3][N],suf[N],pre[N];
int get(){
	int i,j,ans=0x3f3f3f3f;
	for(read(n),i=1;i<=2;i++)for(j=1;j<=n;j++)read(a[i][j]);
	for(pre[1]=a[2][1],i=2;i<=n;i++)pre[i]=pre[i-1]+a[2][i];//前缀和
	for(suf[n]=a[1][n],i=n-1;i>=1;i--)suf[i]=suf[i+1]+a[1][i];//后缀和
	for(i=1;i<=n;i++)ans=min(ans,max(suf[i+1],pre[i-1]));//计算答案
	for(i=1;i<=n;i++)suf[i]=pre[i]=0;
	return printf("%d\n",ans),0;
}
int main(){
	int T;read(T);while(T--)get();
	return 0;
}

谢谢--zhengjun

posted @ 2022-06-11 15:26  A_zjzj  阅读(28)  评论(0编辑  收藏  举报