「LibreOJ β Round #4」游戏

https://loj.ac/problem/524

题目描述

qmqmqm和sublinekelzrip要进行一场游戏,其规则是这样的:

首先有一个序列,其中每个位置是一个整数或是X。双方轮流将X的位置填入此前不在序列中的实数,直到序列中充满数字为止。qmqmqm优先填数。若最后这个序列的逆序对数目为奇数,则qmqmqm获得胜利,否则sublinekelzrip获得胜利。qmqmqm想知道若双方均采取最优决策,在一个给定的序列下他能否获胜。设最终序列中第iii个数为aia_iai​​,则逆序对为满足i<ji<ji<j且ai>aja_i>a_jai​​>aj​​的有序对(i,j)(i,j)(i,j)的数目

注意虽然起始序列中只有整数,但可以填入非整数的实数。

输入格式

第一行包含一个正整数nnn,表示序列的长度。

之后nnn行,每行或为一个整数aia_iai​​,或为一个字符X。

输出格式

输出仅包含一个字符,若qmqmqm获胜,输出W,否则输出L

样例

样例输入1

2
X
X

样例输出1

L

样例输入2

2
X
57

样例输出2

W

X为实数意味着X可以填任何数
当序列长度>1时,先手和后手都可以通过X的值任意改变逆序对的奇偶
所以只要X为奇数个,先手必败,否则,先手必胜
特判:n=1先手必败
当序列没有X时,归并排序求一遍逆序对即可
#include<cstdio>
#include<cstring>
using namespace std;
char c[20];
int a[100001],tmp[100001],len;
long long tot;
void solve(int l,int r)
{
    if(l==r) return;
    int mid=l+r>>1;
    solve(l,mid);
    solve(mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid && j<=r)
    {
        if(a[i]>a[j]) 
        {
            tot+=mid-i+1;
            tmp[k++]=a[j++];
        }
        else tmp[k++]=a[i++];
    }
    while(i<=mid) tmp[k++]=a[i++];
    while(j<=r) tmp[k++]=a[j++];
    for(int i=l;i<=r;i++) a[i]=tmp[i];
}
int main()
{
    int n;
    scanf("%d",&n);
    int sum=0; 
    for(int i=1;i<=n;i++)
    {
        scanf("%s",c);
        if(c[0]=='X') sum++;
        else 
        {
            len=strlen(c);
            int s=0;
            if(c[0]=='-') s=1;
            for(int j=s;j<len;j++) a[i]=a[i]*10+c[j]-'0';
            if(s&1) a[i]=-a[i];
        }
    } 
    if(n==1)  { putchar('L'); return 0; }
    if(!sum)  
    { 
        solve(1,n); 
        if(tot&1) putchar('W');
        else putchar('L');
        return 0; 
    }
    if(sum&1) putchar('W');
    else putchar('L');
} 

 

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7468733.html