Educational Codeforces Round 96 D. String Deletion

题意:

给你一段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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值