HDU_4701_Game

来源:互联网 发布:小型图书馆源码 编辑:程序博客网 时间:2024/04/24 12:37

令si=Ci+Ci+1+++++Cn;

设先手有x元,后手有y元;

设 win(i,x) 表示当前可以买的物品是 i,先手有 x 元,先手是否必胜;

win(i,x)等价于  存在j>i,使得x>=si-sj且 win(j,y)==0;

不难证明,当先手有a元可以必胜时,当先手钱数>=a亦必胜;

设m(i)是当前可以买的物品是i时,必胜所需要的最少钱数,故win(i,x)==1等价于x>=m(i);

m(i)=min{x: 存在j>i,使得x>si-sj且 win(j,y)==0}

因为:A+B-s1+si==x +y

故:m(i)=min{x: 存在j>i,使得x>=si-sj且 win(j,A+B-s1+si-x)==0}

又因为:win(i,x)==1等价于x>=m(i),即win(i,x)==0等价于x<=m(i)-1;

故:m(i)=min{x: 存在j>i,使得x>=si-sj且 A+B-s1+si-x<m(j)-1};

即:m(i)=min{x: 存在j>i,使得x>=si-sj且 A+B-s1+si-m(j)+1<x}

即:m(i)=min{max{si-sj,A+B-s1+si-m(j)+1},j>i}

即:m(i)=si+min{max{-sj,A+B-s1-m(j)+1},j>i}


最后再检验A是否大于等于m(1)即可。

//time:800ms#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define ll __int64using namespace std;const int N=1000010;ll sum[N];ll C[N];ll m[N];int main(){    ios::sync_with_stdio(false);    ll a,b,t;    int n,i;    while(cin>>n>>a>>b) {        for(i=1;i<=n;++i) {            cin>>C[i];        }        sum[n]=C[n];        for(i=n-1;i>=1;--i)            sum[i]=C[i]+sum[i+1];        m[n]=sum[n];        t=0;        t=min(t,max(a+b-sum[1]-m[n]+1,-sum[n]));        for(i=n-1;i>0;--i) {            m[i]=sum[i]+t;            t=min(t,max(a+b-sum[1]-m[i]+1,-sum[i]));        }        if(a>=m[1]) cout<<"ALICE\n";        else cout<<"BOB\n";    }}