zoukankan      html  css  js  c++  java
  • 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
    ");
          }else if (flag==2){
            printf("once again
    ");
          }else {
            printf("quailty
    ");
          }
      }
      return 0;
    }

      

  • 相关阅读:
    C#中get和set的写法
    FineUI中Newtonsoft.Json版本报错解决办法
    ExtAspNet和FineUI未将对象引用设置到对象的实例
    【转载】写runat="server"有什么用
    (object sender,EventArgs e)是什么?
    【转载】onclick与onCommand的区别
    简单总结------redis
    将list等分成n份
    将List 分成n个长度由调用者指定的子List
    CountDownLatch 我的应用场景
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11537323.html
Copyright © 2011-2022 走看看