题目大意
n个数,AB交替取走其中一个(取完后位置不变),取的数要和上一个人取得位置相邻,A第一次取或剩下没有相邻的则可以任意取
求当AB都最大化其所取的数之和时的最终结果
n<=3e5,ai<=1e3
题解
不会
当n为偶数时A只会取第一个或者最后一个,然后AB交替取,否则如果取中间的话会分成奇偶两边,B可以取偶数那边来获得另一边的先手,这样对于A来说比直接取更劣
当n为奇数时根据上面可知A只会取偶数位的,然后B取走左/右剩下的,如此直到某个时刻A取走当前区间的第一个
设最后的区间为[l,r],那么A取的是[1,l-1]偶+[l,r]奇+[r+1,n]偶
先取走所有偶数的,变成把一个区间取的奇偶反转,考虑二分答案判断
那么存在多个合法的最终区间,显然B会尽量把这些区间破坏掉,但如果存在一种区间集合{[l[i],r[i]]}满足l[1]=1,r[k]=n,r[i]+2=l[i+1],这样B就搞不了A了,A只需要取两个区间中间的,无论B往那边取最后都会剩下一个
把贡献拆开后维护合法点的min(sumi)即可判断
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define inf 2147483647
#define ll long long
//#define file
using namespace std;
int a[300001],n,i,j,k,l,L,R,Mid,ans,sum;
bool pd(int t)
{
int i,j,k,l,mn=0;
fo(i,1,n)
if ((i&1) && a[i]-mn>=t)
{
if (i==n) return 1;
mn=min(mn,a[i+1]);
}
return 0;
}
int main()
{
#ifdef file
freopen("agc026F.in","r",stdin);
#endif
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]),sum+=a[i];
if (!(n&1))
{
fo(i,1,n) ans+=(i&1)*a[i];
ans=max(ans,sum-ans);
}
else
{
fo(i,1,n) ans+=(!(i&1))*a[i],a[i]=a[i]*((i&1)*2-1)+a[i-1];
L=ans,R=sum;
while (L<R)
{
Mid=(L+R)/2;
if (pd(Mid-ans))
L=Mid+1; else R=Mid;
}
L-=!pd(L-ans),ans=L;
}
printf("%d %d
",ans,sum-ans);
fclose(stdin);
fclose(stdout);
return 0;
}