C. Tokitsukaze and Duel 前缀维护

  枚举每一个连续的K的第一个位置,如果是先手胜利,那么前[1 , i-1 ]和[ i+k , n ]区间要么全是0,要么全是1

  如果能够平局,那么肯定是[1,i-1],以及[ i+k , n]中有两种情况

  有一个区间全为0,并且另外有个区间内部最左边的1和最右边的1距离是大于K

  有一个区间全为1,并且另外有一个区间内部最左边的0和最右边的0的距离是大于K

  或者两个区间均有1或者均有0

  如何后手胜利,那么肯定没有平局出现,也就意味着

  有一个区间全为0,并且另外有个区间内部最左边的1和最右边的1距离是大于K

  有一个区间全为1,并且另外有一个区间内部最左边的0和最右边的0的距离是大于K

  由于不带修改,我们可以很简单维护i位置

  左边第一次出现1的位置,左边第一次出现0的位置

  右边第一次出现1的位置,右边第一次出现0的位置

  然后o(n)判断即可,这也算是比较优秀的做法了吧。。。

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int maxx = 2e5+6;
int l1[maxx];
int l0[maxx];
int r1[maxx];
int r0[maxx];
char s[maxx];
int main(){
  int n,k;
  while(~scanf("%d%d",&n,&k)){
      scanf("%s",s+1);
      for (int i=1;i<=n;i++){
        if (s[i]=='1'){
            l1[i]=i;
            l0[i]=l0[i-1];
        }else {
            l0[i]=i;
            l1[i]=l1[i-1];
        }
      }
      r0[n+1]=n+1;
      r1[n+1]=n+1;
      for (int i=n;i>=1;i--){
        if (s[i]=='1'){
            r1[i]=i;
            r0[i]=r0[i+1];
        }else {
            r0[i]=i;
            r1[i]=r1[i+1];
        }
      }
      int flag=5;
      for (int i=1;i<=n-k+1;i++){
          int ll=1;
          int lr=i-1;
          int rl=i+k;
          int rr=n;
          if(l1[i-1]==0 && r1[i+k]==n+1){
             flag=min(flag,1);
          }
          if(l0[i-1]==0 && r0[i+k]==n+1){
             flag=min(flag,1);
          }
          if (l1[i-1]==0 && l0[n]-r0[i+k]+1<=k){
             flag=min(flag,3);
          }
          if (l0[i-1]==0 && l1[n]-r1[i+k]+1<=k){
             flag=min(flag,3);
          }
          if (r0[n+k]==0 && l1[i-1]-r1[1]+1<=k){
             flag=min(flag,3);
          }
          if (r1[n+k]==0 && l0[i-1]-r0[1]+1<=k){
             flag=min(flag,3);
          }
          if (r1[n+k]==0 && l0[i-1]-r0[1]+1>k){
             flag=min(flag,2);
          }
          if (r0[n+k]==0 && l1[i-1]-r1[1]+1>k){
             flag=min(flag,2);
          }
          if (l1[i-1]==0 && l0[n]-r0[i+k]+1>k){
             flag=min(flag,2);
          }
          if (l0[i-1]==0 && l1[n]-r1[i+k]+1>k){
             flag=min(flag,2);
          }
          if (l1[i-1]!=0 && r1[i+k]!=n+1){
             flag=min(flag,2);
          }
          if (l0[i-1]!=0 && r0[i+k]!=n+1){
             flag=min(flag,2);
          }
      }
      if (flag==1){
        printf("tokitsukaze\n");
      }else if (flag==2){
        printf("once again\n");
      }else {
        printf("quailty\n");
      }
  }
  return 0;
}

 

  

 

posted @ 2019-09-17 21:22  bluefly-hrbust  阅读(140)  评论(0编辑  收藏  举报