思路:
▶ 设 win(i,x,y) 表示当前可以买的物品是 i,先手有 x 元,后 手有 y 元时,先手是否必胜
▶ win(i,x,y) ⇐⇒∃j((j > i)∧(x ≥ si−sj)∧¬win(j,y,x−si +sj))
▶ 其中 si = Ci + Ci+1 +···+ CN
▶ 注意到 x + y = A + B−s1 + si,即 win(i,x) := win(i,x,y)
▶ win(i,x) =⇒ win(i,x + 1)
▶ 设 m(i) = min{x : win(i,x)},则 ¬win(i,x) ⇐⇒ x ≤ m(i)−1
▶ 令 D = A + B−s1 + si
▶ m(i) =min{x : ∃j((j > i)∧(x ≥ si −sj)∧¬win(j,D−x))}
=min{x : ∃j((j > i)∧(x ≥ si −sj)∧D−x ≤ m(j)−1}
=min{max{si −sj,D−m(j) + 1} : j > i}
=min{max{si −sj,A + B−s1 + si −m(j) + +1} : j > i}
=si + min{max{−sj,A + B−s1 −m(j) + 1} : j > i}
▶ 只要测试 A ≥ m(1)
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
using namespace std;
long long s[1000500];
int main ()
{
int n,a,b;
while(scanf("%d%d%d",&n,&a,&b)!=EOF)
{
for(int i=1;i<=n;++i)
scanf("%I64d",&s[i]);
for(int i=n-1;i>=1;--i)
s[i]+=s[i+1];
long long pre_min=0,now_min;
for(int i=n;i>=1;--i)
{
now_min=pre_min+s[i];
pre_min=min(pre_min,max(-s[i],a+b-s[1]+1-now_min));
}
if(a>=now_min)
printf("ALICE\n");
else printf("BOB\n");
}
return 0;
}