[JZOJ5727] [色]和[流泪]||

我们把把一个游戏看成在二维平面上玩,一开始在 (0,0) ( 0 , 0 ) ,从左边删 x+1 x + 1 ,从右边删 y+1 y + 1
那么假如左边删 x x 个,右边删y个,那么 SG(x,y)=0 S G ( x , y ) = 0 ,我们称之为终止态,那么和终止态相邻且不为终止态的点 SG=1 S G = 1 ,称其为边界态。
不难发现对于一个 x x ,终止态只有一个,而且随着x增大 y y 是单调不降的,大概就像一个右上折线。
还有两个小结论:
1. 假设(x+1,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 ,最长的单调区间的右端点的位置(也就是终止态),ci=max(bi+1,bi+1)也就是边界态。就不难二分出 m 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值