CodeForces - 1430D String Deletion (思维)

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:

  1. 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);
  2. 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:

  1. select i=1i=1: we'll get 111010 →→ 11010 →→ 010;
  2. select i=2i=2: we'll get 111010 →→ 11010 →→ 010;
  3. select i=3i=3: we'll get 111010 →→ 11010 →→ 010;
  4. select i=4i=4: we'll get 111010 →→ 11110 →→ 0;
  5. select i=5i=5: we'll get 111010 →→ 11100 →→ 00;
  6. 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,多余的可以单独删除字符时贡献无用功,所以只需要从前向后扫的过程中记录后面多余字符的个数,

(1)如果某段长度==1,从多余字符中先删掉一个,再把该段当作前缀删掉;如果此时没有多余字符了,也就是说后面的段长都为1,那么之后就两两一删就行了

(2)如果某段长度>1,多余字符要减掉该段贡献的多余字符数,

最后可以发现,如果有足够多的多余字符,答案就是连续相同字符段的个数,否则,删第 i 段时没有多余字符了答案就是i - 1 + (tot - i + 2) / 2,tot是连续相同字符段的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 2e5 + 10;

int a[N], b[N];

int main() {
    int t, n;
    string s;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &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;
        bool 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109062080
今日推荐