「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'); }