Another Problem on Strings

Another Problem on Strings

思路

题目的这一句话提示着我要用binary_search,没想到还真是,

这题考察的就是两个知识点,前缀和以及二分查找,二分查找用STL解决了,前缀和也简单,接下来就是两者组合了。

我们假定当前位置的前缀和是 (sum[i]),我们想办法从前面求以(j)为起点(i)为终点的序列,一定有 (sum[i] - sum[j] = k),接下来的事情就简单了,只需要求得(j)的区间就行了

我们分别对(sum[i] - k和sum[i] - k + 1进行lower\_bound)求得区间 ((l, r])正是(j)对应的区间。然后就(ans += r - l)

然后自信的交了一发,没想到(wa on test 4),没错,只过了样例。

这道题目还有一个坑点就是k = 0的时候,上面的方法不能用。所以我就单独分开了一个k = 0的情况讨论。

这个情况比较简单,取 (i) 的时候一定要注意这一位是0,然后就是用(lower \_bound(sum[i])求得l),其 (j) 的取值区间就是((l, i]),答案就是(ans += i - l)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
char str[N];
int sum[N], k, n;
int main() {
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin >> k;
    cin >> (str + 1);
    int n = strlen(str + 1);
    for(int i = 1; i <= n; i++)
        sum[i] = sum[i - 1] + str[i] - '0';
    ll ans = 0;
    if(k) {
        for(int i = 1; i <= n; i++) {
            int l = sum[i] - k, r = sum[i] - k + 1;
            // cout << l << " " << r << endl;
            int pl = lower_bound(sum, sum + 1 + i, l) - sum;
            int pr = lower_bound(sum, sum + 1 + i, r) - sum;
            // cout << pl << " " << pr << endl;
            // cout << "
";
            if((pl == i + 1 || pr == i + 1) && k)  continue;
            // cout << 1 << endl;
            // cout << "
";
            ans += pr - pl;
        }
    }
    else {
        for(int i = 1; i <= n; i++) {
            if(str[i] == '1')   continue;
            int l = lower_bound(sum, sum + 1 + i, sum[i]) - sum;
            ans += i - l;
        }
    }

    cout << ans << "
";
    return 0;
}
原文地址:https://www.cnblogs.com/lifehappiness/p/12825579.html