我們把把一個遊戲看成在二維平面上玩,一開始在 ,從左邊刪 ,從右邊刪 。
那麼假如左邊刪 個,右邊刪 個,那麼 ,我們稱之爲終止態,那麼和終止態相鄰且不爲終止態的點 ,稱其爲邊界態。
不難發現對於一個 ,終止態只有一個,而且隨着 增大 是單調不降的,大概就像一個右上折線。
還有兩個小結論:
1. 假設 必敗,那麼 必敗,這個顯然;
2. 假設 都必勝,那麼 必勝。
考慮第二個結論的證明,其實這裏的 必勝是保證 均不爲終止態。
因爲 必勝則 中有一個必敗。假設是 必敗,那麼 必勝,又因爲 必勝,那麼 必敗,那麼 就必勝了。另一種假設同理。
那麼考慮 這條對角線上( 是終止態或者邊界態),那麼只有三種可能:
1. 全爲必勝;
2. 全爲必敗;
3. 爲邊界態必勝,其餘必敗。
那我們只要預處理 表示左端點爲 ,最長的單調區間的右端點的位置(也就是終止態), 也就是邊界態。就不難二分出 ,假如 是終止態就是情況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;
}