[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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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\n",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("\n");
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("\n");
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("\n");
47 continue;
48 }
49 if (tot%2==0){//Case2
50 for(int i=0;i<n-tot;i++)printf("b");
51 printf("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
132 }
133 }
[atARC112E]Rvom and Rsrev的更多相关文章
- 【BZOJ3506】【Cqoi2014】排序机械臂
传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...
- 【BZOJ1500】【Noi2005】维修数列
题意原题很清楚了. 解题思路:裸的平衡树操作,注意动态开点即可. 细节还是比较多的,具体参见代码吧... #include <stdio.h> #include <algorithm ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- Android控件——Button与ImageButton
1.简单介绍
- C++ 全面刨析使用指针方法 _new _delete
指针 #include<iostream> using namespace std; int main() { ; int* pn;//声明 int* pn = &avr;//初始 ...
随机推荐
- HTML基本标记
头部标记 <head></head> 说明:元素的作用范围是整篇文档.元素中可以有元信息定义.文档样式表定义和脚本等信息,定义在HTML语言头部的内容往往不会在网页上直接显示. ...
- JVM学习笔记——GC垃圾收集器
GC 垃圾收集器 Java 堆内存采用分代回收算法,因此 JVM 针对新生代和老年代提供了多种垃圾收集器. 1. Serial 收集器 Serial 收集器是单线程收集器,采用复制算法. 是最基本的垃 ...
- 题解 「BJOI2018 治疗之雨」
题目传送门 题目大意 有一个初始为 \(p\) 的数,每次操作分为以下两个: 有 \(\frac{1}{m+1}\) 的概率$+1,但是中途 \(p\) 的最大值只能为 \(n\)$ 有 \(k\) ...
- CICD 流水线就该这么玩系列之一
今天给大家分享的是 DevOps 世界中非常流行的一个 GitOps 工具 - Argo CD.如果你还不知道什么是 GitOps,欢迎留言告诉我,根据热度,我会再写一篇详细讲解 GitOps 的文章 ...
- OSI参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)
文章转自:https://blog.csdn.net/weixin_43914604/article/details/104589085 学习课程:<2019王道考研计算机网络> 学习目的 ...
- 力扣 - 剑指 Offer 57 - II. 和为s的连续正数序列
题目 剑指 Offer 57 - II. 和为s的连续正数序列 思路1(双指针/滑动窗口) 所谓滑动窗口,就是需要我们从一个序列中找到某些连续的子序列,我们可以使用两个for循环来遍历查找,但是未免效 ...
- Android 服务名称规则invalid service name 限制16字符以内
今天调试网络服务的时候为了区分,修改了原有服务名称,同时新增了两个服务. 系统运行的时候报错找不到对应的服务 init: no such service 'wpa_supplicant_common' ...
- Python 模块feedparser安装使用
RSS(简易信息聚合) 简易信息聚合(也叫聚合内容)是一种RSS基于XML标准,在互联网上被广泛采用的内容包装和投递协议.RSS(Really Simple Syndication)是一种描述和同步网 ...
- 检查是否是BST 牛客网 程序员面试金典 C++ java Python
检查是否是BST 牛客网 程序员面试金典 C++ java Python 题目描述 请实现一个函数,检查一棵二叉树是否为二叉查找树. 给定树的根结点指针TreeNode* root,请返回一个boo ...
- 无缓存交换 牛客网 程序员面试金典 C++ Python
无缓存交换 牛客网 程序员面试金典 C++ Python 题目描述 请编写一个函数,函数内不使用任何临时变量,直接交换两个数的值. 给定一个int数组AB,其第零个元素和第一个元素为待交换的值,请返回 ...