有2个栈和一些双端队列,每次可以从栈首或双端队列边取走一个数,取走数的和多大的人赢。
如果先手者和后手者都使用最优的策略,最后先手者和后手者分别能够取得的总石子数分别是多少。
对于一个栈,取法唯一,
对双端队列,长度为奇数取法唯一,否则先手可以取走max(所有奇数位,所有偶数位)
1.
1 2 0 4 3 3 4 0 2 1
如果所有序列都是单调(且取的那一边最大)的,取最大那个就行了
现考虑2个贪心
对于栈
a1,a2,a3,...an
1.如果栈底2个元素
a1>a2
,那么取
a2
不优,因为对手可以马上取
a1
,
那么把它放到最后,根据奇偶性取
2.对于双端队列
..ai−1,ai,ai+1..
如果
ai>ai−1,ai>ai+1
那么先取
ai
2侧肯定不优,如果你被迫拿了,对手可以迅速拿走
ai
,剩下的只能是你拿
那么用贡献
δ=ai−1+ai+1−ai
替换
若干次后能保证序列单调,贪心取最大即可
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define MAXN (1000000+10)
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int n;
ll s1=0,s2=0,a[MAXN];
ll s=0,cnt=0;
bool b[MAXN];
class List{
public:
int pre[MAXN],next[MAXN];
int Head,Tail;
List(){
Head=Tail=0;
MEM(pre) MEM(next)
}
void mem(int n) {
Head=1,Tail=n;
For(i,n) pre[i]=i-1,next[i]=i+1;
MEM(b)
}
void del(int p){
if (p==Head) Head=next[p];
if (p==Tail) Tail=pre[p];
pre[next[p]]=pre[p];
next[pre[p]]=next[p];
}
bool work1() {
bool flag=0;
while( b[Head] && b[next[Head]] && a[Head]>=a[ next[Head] ] ) {
if (cnt&1) s1+=a[Head], s2+=a[next[Head]];
else s1+=a[next[Head]], s2+=a[Head];
del(Head); del(Head);
flag=1;
}
while( b[Tail] && b[pre[Tail]] && a[Tail]>=a[ pre[Tail] ] ) {
if (cnt&1) s1+=a[Tail], s2+=a[pre[Tail]];
else s1+=a[pre[Tail]], s2+=a[Tail];
del(Tail); del(Tail);
flag=1;
}
return flag;
}
bool work2() {
bool flag=0;
for(int i=next[Head]; next[i] ; i=next[i] ) {
if (b[ pre[ i ] ] && b[i] && b[next[i]] && a[pre[i]] <a[i] && a[i]> a[next[i]] )
{
a[i] = a[ pre [ i ] ] + a[ next[i]] - a[i];
del(pre[i]); del(next[i]);
flag=1;
}
}
return flag;
}
ll ans[MAXN];
int siz;
void work() {
while (work1() || work2() );
siz=0;
for(int i=Head;i<=Tail;i=next[i]) if (b[i]) ans[++siz] = a[i] ;
sort(ans+1,ans+1+siz);
ll s3=s-s1-s2,p=0;
bool flag=1;
ForD(i,siz) {
if (flag) p+=ans[i];else p-=ans[i];
flag^=1;
}
cout<<s1 + (s3+p)/2<<' '<<s2+(s3-p)/2<<endl;
}
}S;
int main()
{
// freopen("bzoj2000.in","r",stdin);
// freopen(".out","w",stdout);
cin>>n;
S.mem(n);
For(i,n) scanf("%lld",&a[i]),s+=a[i], b[i]=(bool)a[i] ,cnt+=(bool)a[i];
S.work();
return 0;
}