[JZOJ5727] [色]和[流淚]||

我們把把一個遊戲看成在二維平面上玩,一開始在(0,0) ,從左邊刪x+1 ,從右邊刪y+1
那麼假如左邊刪x 個,右邊刪y 個,那麼SG(x,y)=0 ,我們稱之爲終止態,那麼和終止態相鄰且不爲終止態的點SG=1 ,稱其爲邊界態。
不難發現對於一個x ,終止態只有一個,而且隨着x 增大y 是單調不降的,大概就像一個右上折線。
還有兩個小結論:
1. 假設(x+1,y+1) 必敗,那麼(x,y) 必敗,這個顯然;
2. 假設(x+1,y+1),(x+2,y+2) 都必勝,那麼(x,y) 必勝。
考慮第二個結論的證明,其實這裏的(x+2,y+2) 必勝是保證(x,y+2),(x+1,y+2),(x+2,y+1),(x+2,y) 均不爲終止態。
因爲(x+1,y+1) 必勝則(x+2,y+1),(x+1,y+2) 中有一個必敗。假設是(x+2,y+1) 必敗,那麼(x+2,y) 必勝,又因爲(x+1,y+1) 必勝,那麼(x+1,y) 必敗,那麼(x,y) 就必勝了。另一種假設同理。
那麼考慮(0,0),(1,1),...,(m,m) 這條對角線上((m,m) 是終止態或者邊界態),那麼只有三種可能:
1. 全爲必勝;
2. 全爲必敗;
3. (m,m) 爲邊界態必勝,其餘必敗。
那我們只要預處理bi 表示左端點爲i ,最長的單調區間的右端點的位置(也就是終止態),ci=max(bi+1,bi+1) 也就是邊界態。就不難二分出m ,假如(m,m) 是終止態就是情況2,否則雙方要麼一直刪左邊,要麼一直刪右邊,只要再二分一下兩種情況走到邊界態的長度,然後判一下奇偶性(全奇必敗,有偶必勝)即可。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000010
using namespace std;
int n,m,ty,a[N],b[N],c[N];
int read()
{
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int main()
{
    freopen("gameb.in","r",stdin);
    freopen("gameb.out","w",stdout);
    n=read();ty=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=n,p=n;i;i--)
    {
        if(a[i+1]<a[i]) p=i;
        b[i]=p;
    }
    if(ty==2)
    for(int i=n,p=n;i;i--)
    {
        if(a[i+1]>a[i]) p=i;
        b[i]=max(b[i],p);
    }
    for(int i=1;i<=n;i++)
        c[i]=max(b[i+1],b[i]+1);
    m=read();
    while(m--)
    {
        int l=read(),r=read(),L=0,R=(r-l+1)/2,u,v;
        if(b[l]>=r) {puts("liulei");continue;}
        if(c[l]>=r) {puts("se");continue;}
        while(L<R)
        {
            int len=(L+R)>>1;
            if(c[l+len]>=r-len) R=len;
            else L=len+1;
        }
        l+=L-1;r-=L-1;

        L=0;R=r-l+1;
        while(L<R)
        {
            int len=(L+R)>>1;
            if(c[l+len]>=r) R=len;
            else L=len+1;
        }
        u=L;

        L=0;R=r-l+1;
        while(L<R)
        {
            int len=(L+R)>>1;
            if(c[l]>=r-len) R=len;
            else L=len+1;
        }
        v=L;

        if((u&1)&&(v&1)) puts("liulei");
        else puts("se");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章