codeforces 1430D

给定一个01字符串,每次操作可以删除一个字符,然后删除所有与其相同的前缀。求最大操作次数。示例中,对于字符串111010,最大操作次数为3,具体操作为:选i=2得010,再选i=3得1,最后选i=1得空字符串。
摘要由CSDN通过智能技术生成

You have a string ss consisting of nn characters. Each character is either 0 or 1.

You can perform operations on the string. Each operation consists of two steps:

select an integer ii from 11 to the length of the string ss, then delete the character sisi (the string length gets reduced by 11, the indices of characters to the right of the deleted one also get reduced by 11);
if the string ss is not empty, delete the maximum length prefix consisting of the same characters (the indices of the remaining characters and the string length get reduced by the length of the deleted prefix).
Note that both steps are mandatory in each operation, and their order cannot be changed.

For example, if you have a string s=s= 111010, the first operation can be one of the following:

select i=1i=1: we’ll get 111010 →→ 11010 →→ 010;
select i=2i=2: we’ll get 111010 →→ 11010 →→ 010;
select i=3i=3: we’ll get 111010 →→ 11010 →→ 010;
select i=4i=4: we’ll get 111010 →→ 11110 →→ 0;
select i=5i=5: we’ll get 111010 →→ 11100 →→ 00;
select i=6i=6: we’ll get 111010 →→ 11101 →→ 01.
You finish performing operations when the string ss becomes empty. What is the maximum number of operations you can perform?

Input

The first line contains a single integer tt (1≤t≤10001≤t≤1000) — the number of test cases.

The first line of each test case contains a single integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the length of the string ss.

The second line contains string ss of nn characters. Each character is either 0 or 1.

It’s guaranteed that the total sum of nn over test cases doesn’t exceed 2⋅1052⋅105.

Output

For each test case, print a single integer — the maximum number of operations you can perform.

Example

Input

5
6
111010
1
0
1
1
2
11
6
101010
Output

3
1
1
1
3
Note

In the first test case, you can, for example, select i=2i=2 and get string 010 after the first operation. After that, you can select i=3i=3 and get string 1. Finally, you can only select i=1i=1 and get empty string.

题意

01字符串 每一步操作可以删除任意一个字符
然后 从第一个字符开始 相同的都会被删去 一大步(两小步)

思路

如果说目前相同字符长度为1 那么就在后面多余字符中删
否则 就删掉这个相同字符

如果没有多余字符 长度都为1 那么就是删一个去一个 答案即i-1 +(tot-i+2)/2;

#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
ll read(){ll res = 0, ch, flag = 0;if((ch = getchar()) == '-')flag = 1;else if(ch >= '0' && ch <= '9')res = ch - '0';while((ch = getchar()) >= '0' && ch <= '9' )res = res * 10 + ch - '0';return flag ? -res : res;}
const int maxn =1e6+199 ;
ll sum=0;
ll n,m,k,w,ans=0,cnt=0;
ll dp[maxn];
int a[maxn];
ll b[maxn];
char c[maxn];
ll mod=1e9+7;

int main()
{

     int t;
    string s;
    scanf("%d", &t);
    while(t--) {
        scanf("%lld", &n);
        cin >> s;
        int now = 1, tot = 0;
        for(int i = 1; i < n; ++i) {
            if(s[i] == s[i - 1]) now++;
            else {
                a[++tot] = now;
                now = 1;
            }
        }
        a[++tot] = now;
        int cnt = 0;
        for(int i = 1; i <= tot; ++i) cnt += a[i] - 1;
        int ans = 0, tmp = 0;
        int flag = 0;
        for(int i = 1; i <= tot; ++i) {
            if(!cnt) {
                ans = i - 1 + (tot - i + 2) / 2;
                flag = 1;
                break;
            }
            cnt--;
            tmp++;
            if(a[i] - 1 > tmp) {
                a[i] -= tmp;
                tmp = 0;
            }
            else {
                tmp -= a[i] - 1;
                a[i] = 1;
            }
            cnt -= a[i] - 1;
        }
        if(!flag) ans = tot;
        printf("%d\n", ans);
    }

    return 0;
}

还有一种方法
就是看看目前这个相同的字符串能消除前面几个不同的字符串

最后在整理一下后面没被消除的

int t,n,d,m,i;
	string s;
	cin>>t;
	while(t--){
		cin>>n>>s;
		d=1, m=0;
		for(i=1; i<(int) s.length(); i++){
			if(s[i-1] !=s[i]) d++;
			else m++;
			m=min(m, d);
		}
			m +=(d-m+1)/2;
			cout<<m<<endl;
		}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛郎恋刘娘,刘娘念牛郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值