毒瘤分类讨论题

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

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. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 int t;
  4. 4 char s[200005];
  5. 5 int main(){
  6. 6 scanf("%d",&t);
  7. 7 while (t--){
  8. 8 scanf("%s",s);
  9. 9 int n=strlen(s),tot=0;
  10. 10 if (n<=2){//Case0
  11. 11 printf("%s\n",s);
  12. 12 continue;
  13. 13 }
  14. 14 for(int i=0;i<n;i++)
  15. 15 if (s[i]=='a')tot++;
  16. 16 if (s[n-1]=='a'){//Case1
  17. 17 for(int i=0;i<n-tot;i++)printf("b");
  18. 18 int one=0,sum=0;
  19. 19 if (s[n-2]=='a'){//Case1.1
  20. 20 for(int i=0;i<n;i++)
  21. 21 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
  22. 22 if ((!i)||(s[i-1]=='b'))one++;
  23. 23 else sum++;
  24. 24 }
  25. 25 sum+=(one+1)/2;
  26. 26 for(int i=0;i<tot-2*sum;i++)printf("a");
  27. 27 printf("\n");
  28. 28 continue;
  29. 29 }
  30. 30 //Case1.2
  31. 31 bool flag=0;
  32. 32 for(int i=0;i<n-2;i++)
  33. 33 if ((s[i]=='a')&&(s[i+1]=='a')&&(s[i+2]=='a'))flag=1;
  34. 34 if (!flag){//Case1.2.1
  35. 35 if (tot&1)printf("a");
  36. 36 printf("\n");
  37. 37 continue;
  38. 38 }
  39. 39 for(int i=0;i<n;i++)
  40. 40 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
  41. 41 if ((!i)||(s[i-1]=='b'))one++;
  42. 42 else sum++;
  43. 43 }
  44. 44 sum+=(one+1)/2;
  45. 45 for(int i=0;i<tot-2*sum;i++)printf("a");
  46. 46 printf("\n");
  47. 47 continue;
  48. 48 }
  49. 49 if (tot%2==0){//Case2
  50. 50 for(int i=0;i<n-tot;i++)printf("b");
  51. 51 printf("\n");
  52. 52 continue;
  53. 53 }
  54. 54 int flag=0,las=-1;
  55. 55 for(int i=1;i<n;i++)
  56. 56 if ((s[i-1]=='b')&&(s[i]=='a'))flag=1;
  57. 57 for(int i=0;i<n;i++)
  58. 58 if (s[i]=='a')las=i;
  59. 59 if ((!flag)||(las>=n-3)){//Case3
  60. 60 for(int i=0;i<las;i++)
  61. 61 if (s[i]=='b')printf("b");
  62. 62 printf("a");
  63. 63 for(int i=las+1;i<n;i++)
  64. 64 if (s[i]=='b')printf("b");
  65. 65 printf("\n");
  66. 66 continue;
  67. 67 }
  68. 68 //Case4
  69. 69 for(int i=0;i<n-tot-2;i++)printf("b");
  70. 70 if (s[0]!='a'){//Case4.1
  71. 71 bool flag=0;
  72. 72 for(int i=0;i<n-1;i++)
  73. 73 if ((s[i]=='a')&&(s[i+1]=='a'))flag=1;
  74. 74 if (!flag){//Case4.1.1
  75. 75 if (tot&1)printf("a");
  76. 76 printf("\n");
  77. 77 continue;
  78. 78 }
  79. 79 //Case4.1.2
  80. 80 int one=0,sum=-1;
  81. 81 for(int i=0;i<n;i++)
  82. 82 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
  83. 83 if ((!i)||(s[i-1]=='b'))one++;
  84. 84 else sum++;
  85. 85 }
  86. 86 sum+=(one+1)/2;
  87. 87 for(int i=0;i<tot-2*sum;i++)printf("a");
  88. 88 printf("\n");
  89. 89 continue;
  90. 90 }
  91. 91 //Case4.2
  92. 92 flag=0;
  93. 93 for(int i=0;i<n-1;i++){
  94. 94 if ((s[i]=='b')&&(!flag))flag=1;
  95. 95 if ((flag)&&(s[i]=='a')&&(s[i+1]=='a'))flag=2;
  96. 96 }
  97. 97 if ((s[1]=='b')||(flag>1)){//Case4.2.1
  98. 98 bool flag=0;
  99. 99 for(int i=0;i<n-1;i++)
  100. 100 if ((s[i]=='a')&&(s[i+1]=='a'))flag=1;
  101. 101 if (!flag){
  102. 102 if (tot&1)printf("a");
  103. 103 printf("\n");
  104. 104 continue;
  105. 105 }
  106. 106 int one=0,sum=-1;
  107. 107 for(int i=0;i<n;i++)
  108. 108 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
  109. 109 if ((!i)||(s[i-1]=='b'))one++;
  110. 110 else sum++;
  111. 111 }
  112. 112 sum+=(one+1)/2;
  113. 113 for(int i=0;i<tot-2*sum;i++)printf("a");
  114. 114 printf("\n");
  115. 115 continue;
  116. 116 }
  117. 117 //Case4.2.2
  118. 118 if ((s[0]!='a')||(s[1]!='a')||(s[2]!='a')){
  119. 119 if (tot&1)printf("a");
  120. 120 printf("\n");
  121. 121 continue;
  122. 122 }
  123. 123 int one=-1,sum=0;
  124. 124 for(int i=0;i<n;i++)
  125. 125 if ((s[i]=='a')&&(i<n-1)&&(s[i+1]=='b')){
  126. 126 if ((!i)||(s[i-1]=='b'))one++;
  127. 127 else sum++;
  128. 128 }
  129. 129 sum+=(one+1)/2;
  130. 130 for(int i=0;i<tot-2*sum;i++)printf("a");
  131. 131 printf("\n");
  132. 132 }
  133. 133 }

[atARC112E]Rvom and Rsrev的更多相关文章

  1. 【BZOJ3506】【Cqoi2014】排序机械臂

    传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...

  2. 【BZOJ1500】【Noi2005】维修数列

    题意原题很清楚了. 解题思路:裸的平衡树操作,注意动态开点即可. 细节还是比较多的,具体参见代码吧... #include <stdio.h> #include <algorithm ...

  3. BZOJ3223文艺平衡树——非旋转treap

    此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  4. Android控件——Button与ImageButton

    1.简单介绍

  5. C++ 全面刨析使用指针方法 _new _delete

    指针 #include<iostream> using namespace std; int main() { ; int* pn;//声明 int* pn = &avr;//初始 ...

随机推荐

  1. 如何基于Jupyter notebook搭建Spark集群开发环境

    摘要:本文介绍如何基于Jupyter notebook搭建Spark集群开发环境. 本文分享自华为云社区<基于Jupyter Notebook 搭建Spark集群开发环境>,作者:apr鹏 ...

  2. 利用OpenCV存储一段视频中的每一帧

    // vfc.cpp : 定义控制台应用程序的入口点.#include "stdafx.h"#include <opencv2/highgui/highgui.hpp> ...

  3. 5 大场景深度探讨何为 Serverless 架构模式?

    作者 | Hongqi 阿里云高级技术专家 究竟什么是 Serverless 架构? 什么是 Serverless 架构?按照 CNCF 对 Serverless 计算的定义,Serverless 架 ...

  4. GDP区域分布图的生成与对比(ArcPy实现)

    一.背景 各地区经济协调发展是保证国民经济健康持续稳定增长的关键.GDP是反映各地区经济发展状况的重要指标.科学准确分析各地区GDP空间分布特征,对制定有效措施,指导经济协调发展具有重要参考价值. 二 ...

  5. 洛谷4366——最短路(dijkstra,思维,异或)

    题目大意 给定一个n个点,m条边的图,每条边有边权,而每个点\(i\)也可以直接到达\(j\),代价是\(i\ xor\ j\),给定一个S和T,求S到T的最小代价 其中\(n\le100000,m\ ...

  6. FastAPI 学习之路(十二)接口几个额外信息和额外数据类型

    系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...

  7. 2021.3.10--vj补题

    B - Saving the City cf--1443B Bertown is a city with nn buildings in a straight line. The city's sec ...

  8. pycharm中安装和使用sqlite过程详解

    创建Django项目,添加app 使用虚拟环境 项目创建默认使用的Django数据库是sqlite 配置静态文件 STATIC_URL = '/static/' # HTML中使用的静态文件夹前缀 S ...

  9. 2020年OO助教工作总结

    随着这学期课程的落幕,我一学期的OO助教工作也宣告结束.这学期我的工作主要在系统组,和OO后台的数据库打交道. 作业查重 我几乎每周都会做的例行工作,是对每周的homework进行查重管理.由于使用了 ...

  10. gson中TypeAdapter实现自定义序列化操作

    最近在项目中遇到这么一个问题,我们后台需要向前端返回一个 json 数据,就是将一个地理位置对象以json的格式返回到前台,但是这个地理位置对象中的经纬度是Double数据类型,项目中规定,如果经纬度 ...