题意:
给你一段01序列,每次操作(以下是一次操作的两个步骤):
1、你选择一个数删去。
2、前缀和相同的都删去(例如:110011,就删去前两个1,具体看样例)
问最多能执行几次操作。
解题思路:
我是这样做的:首先如果没有第1步,那么答案就是连续相同段的段数,现在考虑第1步:
1、如果当前段连续相同的数字个数超过1,那么我就从中选一个执行第1步(反正这个操作2中也一定会被删去)
2、如果当前段连续相同的数字个数只有1,如果我现在删除这个数,那么第二步将会删除下一段相同的数(也就是说答案会减少),那么考虑不删除这个数有不会让答案减少,看3。
3、如果当前段连续相同的数字个数超过2,那么多出来的数我可以为前面2做贡献,也就是当遇到情况2时,我可以选择删除一个当前段的数。
如果还剩下没办法通过情况3来优化的情况2,那么只能删除了,也就是每次操作删除了连段相同段。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
const int mod = 1e9+7;
int main(){
int t;
cin>>t;
string s;
while(t--)
{
int n;
cin>>n>>s;
s+='+';
int ans=0,c=0,cnt=0;
for(int i=0;i<n;i++)
{
if(i==0||s[i]!=s[i-1])//计算连续相同段
{
ans++;
cnt=1;
}
if((i==0||s[i]!=s[i-1]) &&s[i]!=s[i+1])//情况2
c++;
if(i>0 && s[i]==s[i-1])
{
cnt++;
if(cnt>2)//情况3
{
c--;
c=max(0,c);
}
}
}
cout<<ans-c/2<<endl;
}
return 0;
}