传送门
题面描述
文章图片
输入样例
5
10
1110011000
8
11001111
2
00
2
11
6
100110
输出样例
3 2
0 3
0 1
0 1
3 1
题意
给定一个长度为偶数且仅包含0 0 0 和1 1 1 的字符串,每次操作可以任选一个字符并翻转,要求最后该字符串能够划分为若干段,每一段内都是偶数个相同字符,问符合题意的最小操作次数,以及在该操作次数下划分得到的最少段的数量。
结论妙妙题(即使标的知识点是d p dp dp)
由于最终需要形成每一段内为偶数个相同字符,因此可以考虑遍历所有下标为偶数(默认从0 0 0 开始)的字符,并判断该字符是否与后一字符相同。当不相同时,说明需要对这两个相邻字符进行至少一次改动。
例: 111000 111000 111000,最少需要对中间的10 10 10 中选择一个进行翻转,由此可以得到需要的最少操作次数,因为相邻的两个不同一定能够通过翻转一个,使得这两个字符构成一个合法段。
当然,也可能存在类似该情景的特殊情况,如: 001000 001000 001000,在确定了最少操作次数的情况下,该样例可能得到的最少段数量为1 1 1 或2 2 2,具体需要判断其两侧存在的段情况。
由例: 111000 111000 111000 可得,对于中间的10 10 10 字符,可以通过选定翻转字符的方式,令其向前融合( 111100 111100 111100)或向后融合( 110000 110000 110000)。容易扩展到,对于任意两个相邻但不相等的字符,一定能够让其融合于任一侧。(不要忘记这两个相邻字符需要满足前一个字符的下标为偶数)
【神仙|B2. Tokitsukaze and Good 01-String (hard version)】因此可以将本题转化为,求字符串中已经固定的不同段的数量。例: 111000011000 111000011000 111000011000,可划分为111000011000 11\ 10\ 00\ 01\ 10\ 00 11 10 00 01 10 00,由于其中01 01 01、 10 10 10 的特殊性,可以先做忽略,得到110000 11\ 0000 11 0000 共两个不同段。
#include
#define int long longusing namespace std;
vector q;
void solve(){
int n,ans=0,cnt=0;
cin>>n;
string s;
cin>>s;
q.clear();
for(int i=0;
i>T;
while(T--)
solve();
return 0;
}
推荐阅读
- #yyds干货盘点#项目实战 <-; DeepSORT算法实现车辆和行人跟踪计数和是否道路违规检测
- windows11 安装vc++6.0
- 『数据结构与算法』栈(原理与实现)
- 经验分享|五月集训总结——来自小风
- 无糖的五月集训总结
- 在lc被欺负的这些年|【五月集训】—— 汇聚星球,算法锤炼,集中一点,登峰造极
- 算法|【剑指offer】26.树的子结构
- 网络|TCP/IP Socket网络编程
- 6.机器学习|马尔可夫链算法原理与实现