我们把把一个游戏看成在二维平面上玩,一开始在
(0,0)
(
0
,
0
)
,从左边删
x+1
x
+
1
,从右边删
y+1
y
+
1
。
那么假如左边删
x
x
个,右边删个,那么
SG(x,y)=0
S
G
(
x
,
y
)
=
0
,我们称之为终止态,那么和终止态相邻且不为终止态的点
SG=1
S
G
=
1
,称其为边界态。
不难发现对于一个
x
x
,终止态只有一个,而且随着增大
y
y
是单调不降的,大概就像一个右上折线。
还有两个小结论:
1. 假设必败,那么
(x,y)
(
x
,
y
)
必败,这个显然;
2. 假设
(x+1,y+1),(x+2,y+2)
(
x
+
1
,
y
+
1
)
,
(
x
+
2
,
y
+
2
)
都必胜,那么
(x,y)
(
x
,
y
)
必胜。
考虑第二个结论的证明,其实这里的
(x+2,y+2)
(
x
+
2
,
y
+
2
)
必胜是保证
(x,y+2),(x+1,y+2),(x+2,y+1),(x+2,y)
(
x
,
y
+
2
)
,
(
x
+
1
,
y
+
2
)
,
(
x
+
2
,
y
+
1
)
,
(
x
+
2
,
y
)
均不为终止态。
因为
(x+1,y+1)
(
x
+
1
,
y
+
1
)
必胜则
(x+2,y+1),(x+1,y+2)
(
x
+
2
,
y
+
1
)
,
(
x
+
1
,
y
+
2
)
中有一个必败。假设是
(x+2,y+1)
(
x
+
2
,
y
+
1
)
必败,那么
(x+2,y)
(
x
+
2
,
y
)
必胜,又因为
(x+1,y+1)
(
x
+
1
,
y
+
1
)
必胜,那么
(x+1,y)
(
x
+
1
,
y
)
必败,那么
(x,y)
(
x
,
y
)
就必胜了。另一种假设同理。
那么考虑
(0,0),(1,1),...,(m,m)
(
0
,
0
)
,
(
1
,
1
)
,
.
.
.
,
(
m
,
m
)
这条对角线上(
(m,m)
(
m
,
m
)
是终止态或者边界态),那么只有三种可能:
1. 全为必胜;
2. 全为必败;
3.
(m,m)
(
m
,
m
)
为边界态必胜,其余必败。
那我们只要预处理
bi
b
i
表示左端点为
i
i
,最长的单调区间的右端点的位置(也就是终止态),也就是边界态。就不难二分出
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;
}