zoukankan      html  css  js  c++  java
  • [atARC112E]Rvom and Rsrev

    毒瘤分类讨论题

    (注:以下情况都有“之前的情况都不满足的”前提条件,并用斜体表示一些说明)

    Case0:若$|s|le 2$,直接输出即可,因此假设$|s|>3$

    首先,我们最希望在不对$b$操作的前提下(不减小$b$的数量)使得所有$b$都在最前面,此时即最大化后缀$a$的数量,由于每一次操作减少两个$a$,即最小化操作数

    Case1:以$a$为结尾(不难证明此时总是可以达到我们最希望的情况)

    Case1.1:以$aa$为结尾,将$a$通过$b$划分为若干个非空段,根据长度分为两类:

    1.对于非结尾且长度大于1的段,将该段第一个$a$与结尾段的第一个$a$操作,每一段多1次操作

    2.对于(非结尾且)长度为1的段,与同类的段相互抵消,需要段数除以2上取整次操作

    Case1.2:以$ba$为结尾,同样将其划分后,再分类讨论

    Case1.2.1:若不存在长度大于2的段,则永远无法使得最终结尾$a$的个数大于1,因此最终个数取决于初始$a$个数的奇偶性(即0或1)

    Case1.2.2:无特殊限制(存在长度大于2的段),将该段第一个$a$与结尾的$a$操作后,即与Case1.1相同

    事实上,由于恰好不考虑最后一段$a$以及每一段$a$都要一次操作,所以与Case1.1完全相同

    Case2:$a$的个数为偶数,此时直接成对来删除所有$a$即可

    如果不满足Case1和Case2,那么是达不到最希望的情况的,此时根据是否对$b$操作来分类

    对$b$操作的基本思路是将末尾的$b$与一个$a$之前的$b$操作使得以$a$为结尾,那么至少要损失两个$b$,同时能够做到让剩下的$b$都在最前面

    Case3:整个字符串中不存在形如$ba$的形式,或以$abb$、$ab$结尾

    此时选择不对$b$操作,显然保留最后的$a$,将其余$a$成对消除即可

    Case4:无特殊条件(不满足Case1、Case2和Case3)

    Case4.1:不以$a$为开头

    注意到与长度大于1的段之前的$b$操作一定会使得答案减小2,而与长度为1的段之前的$b$操作至多使答案减小2,因此显然与长度大于1的段之前的$b$操作

    Case4.1.1:不存在长度大于1的段,那么与Case1.2.1相同,最终结尾的$a$个数即初始$a$个数奇偶性

    Case4.1.2:存在长度大于1的段,将末尾的$b$与该段开头的$b$操作后与Case1.1相同

    Case4.2:以$a$为开头

    Case4.2.1:以$ab$为开头或存在不在开头且长度大于1的段,此时与Case4.1同样操作即可

    Case4.2.2:无特殊限制(以$aa$为开头且不存在不在开头且长度大于1的段),此时先将末尾的$b$与任意一个$a$之前的$b$(长度都是1)操作,之后与Case1.2相同

    先将开头的$a$与某一个$a$操作是等价的,此时对应于Case4.1

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int t;
      4 char s[200005];
      5 int main(){
      6     scanf("%d",&t);
      7     while (t--){
      8         scanf("%s",s);
      9         int n=strlen(s),tot=0;
     10         if (n<=2){//Case0
     11             printf("%s
    ",s);
     12             continue;
     13         }
     14         for(int i=0;i<n;i++)
     15             if (s[i]=='a')tot++;
     16         if (s[n-1]=='a'){//Case1
     17             for(int i=0;i<n-tot;i++)printf("b");
     18             int one=0,sum=0;
     19             if (s[n-2]=='a'){//Case1.1
     20                 for(int i=0;i<n;i++)
     21                     if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
     22                         if ((!i)||(s[i-1]=='b'))one++;
     23                         else sum++;
     24                     }
     25                 sum+=(one+1)/2;
     26                 for(int i=0;i<tot-2*sum;i++)printf("a");
     27                 printf("
    ");
     28                 continue;
     29             }
     30             //Case1.2
     31             bool flag=0;
     32             for(int i=0;i<n-2;i++)
     33                 if ((s[i]=='a')&&(s[i+1]=='a')&&(s[i+2]=='a'))flag=1;
     34             if (!flag){//Case1.2.1
     35                 if (tot&1)printf("a");
     36                 printf("
    ");
     37                 continue;
     38             }
     39             for(int i=0;i<n;i++)
     40                 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
     41                     if ((!i)||(s[i-1]=='b'))one++;
     42                     else sum++;
     43                 }
     44             sum+=(one+1)/2;
     45             for(int i=0;i<tot-2*sum;i++)printf("a");
     46             printf("
    ");
     47             continue;
     48         }
     49         if (tot%2==0){//Case2
     50             for(int i=0;i<n-tot;i++)printf("b");
     51             printf("
    ");
     52             continue;
     53         }
     54         int flag=0,las=-1;
     55         for(int i=1;i<n;i++)
     56             if ((s[i-1]=='b')&&(s[i]=='a'))flag=1;
     57         for(int i=0;i<n;i++)
     58             if (s[i]=='a')las=i;
     59         if ((!flag)||(las>=n-3)){//Case3
     60             for(int i=0;i<las;i++)
     61                 if (s[i]=='b')printf("b");
     62             printf("a");
     63             for(int i=las+1;i<n;i++)
     64                 if (s[i]=='b')printf("b");
     65             printf("
    ");
     66             continue;
     67         }
     68         //Case4
     69         for(int i=0;i<n-tot-2;i++)printf("b");
     70         if (s[0]!='a'){//Case4.1
     71             bool flag=0;
     72             for(int i=0;i<n-1;i++)
     73                 if ((s[i]=='a')&&(s[i+1]=='a'))flag=1;
     74             if (!flag){//Case4.1.1
     75                 if (tot&1)printf("a");
     76                 printf("
    ");
     77                 continue;
     78             }
     79             //Case4.1.2
     80             int one=0,sum=-1;
     81             for(int i=0;i<n;i++)
     82                 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
     83                     if ((!i)||(s[i-1]=='b'))one++;
     84                     else sum++;
     85                 }
     86             sum+=(one+1)/2;
     87             for(int i=0;i<tot-2*sum;i++)printf("a");
     88             printf("
    ");
     89             continue;
     90         }
     91         //Case4.2
     92         flag=0;
     93         for(int i=0;i<n-1;i++){
     94             if ((s[i]=='b')&&(!flag))flag=1;
     95             if ((flag)&&(s[i]=='a')&&(s[i+1]=='a'))flag=2;
     96         }
     97         if ((s[1]=='b')||(flag>1)){//Case4.2.1
     98             bool flag=0;
     99             for(int i=0;i<n-1;i++)
    100                 if ((s[i]=='a')&&(s[i+1]=='a'))flag=1;
    101             if (!flag){
    102                 if (tot&1)printf("a");
    103                 printf("
    ");
    104                 continue;
    105             }
    106             int one=0,sum=-1;
    107             for(int i=0;i<n;i++)
    108                 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
    109                     if ((!i)||(s[i-1]=='b'))one++;
    110                     else sum++;
    111                 }
    112             sum+=(one+1)/2;
    113             for(int i=0;i<tot-2*sum;i++)printf("a");
    114             printf("
    ");
    115             continue;
    116         }
    117         //Case4.2.2
    118         if ((s[0]!='a')||(s[1]!='a')||(s[2]!='a')){
    119             if (tot&1)printf("a");
    120             printf("
    ");
    121             continue;
    122         }
    123         int one=-1,sum=0;
    124         for(int i=0;i<n;i++)
    125             if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
    126                 if ((!i)||(s[i-1]=='b'))one++;
    127                 else sum++;
    128             }
    129         sum+=(one+1)/2;
    130         for(int i=0;i<tot-2*sum;i++)printf("a");
    131         printf("
    ");
    132     }
    133 }
    View Code
  • 相关阅读:
    洛咕11月月赛部分题解 By cellur925
    POJ 2411 Mondriaan's Dream 【状压Dp】 By cellur925
    Luogu P1637 三元上升子序列【权值线段树】By cellur925
    Luogu P1438无聊的序列【线段树/差分】By cellur925
    Luogu P1558 色板游戏【线段树/状态压缩】By cellur925
    Luogu P4403 [BJWC2008]秦腾与教学评估【二分答案】By cellur925
    Luogu P3941 入阵曲【前缀和】By cellur925
    查询事件状态,mysql查看事件是否开启,设置启动时自动开启方法
    Logback详细整理,基于springboot的日志配置
    使用release自动打包发布正式版详细教程
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14441254.html
Copyright © 2011-2022 走看看