codeforces E. K-periodic Garland

codeforces E. K-periodic Garland_第1张图片

题目

题意:

给你一个 n , k n,k n,k和一个 s s s 01 01 01序列,现在你可以改变其中的 01 01 01使得每个相邻的 1 1 1中都存在 k − 1 k-1 k1 0 0 0,问最少需要改变几个。

思路:

我们可以把序列中的 0 0 0赋值成 − 1 -1 1,然后 1 1 1还是 1 1 1,我们可以因为相邻的为 k k k,所以我们可以将这个看成是 t , t + k , t + 2 ∗ k t,t+k,t+2*k t,t+k,t+2k这个样子,这样相邻的就都是 0 0 0了,所以我们只要枚举 k k k,就行了,然后就是如果求出对于 0 0 0~ k − 1 k-1 k1的每一个数字,我们求出每一个需要改变的字符数,然后取最小值。
我们先算出总共的 1 1 1的个数 c n t cnt cnt,然后我们可以分成两种情况(我们先假设a,b,c是权值一样的连续的 t t t序列, t t t代表着 t , t + k , t + 2 ∗ k . . . t,t+k,t+2*k... t,t+k,t+2k...这样的)。

  • a b c ( a = − 1 , b = 1 , c = − 1 ) a b c(a=-1,b=1,c=-1) abc(a=1,b=1,c=1)这种情况我们不需要改变的 1 1 1的个数就是 ∣ b ∣ |b| b,所以我们最后的需要改变的个数就是 c n t − ∣ b ∣ cnt-|b| cntb
  • a b c ( a = 1 , b = − 1 , c = 1 ) abc(a=1,b=-1,c=1) abc(a=1,b=1,c=1)这种情况有 a + c a+c a+c 1 1 1是不需要改变的,我们需要把中间的 b b b 0 0 0 变为 1 1 1,还需要把 c n t − a − c cnt−a−c cntac 个其他位置的 1 1 1 变为 0 0 0。即 b + c n t − a − c b+cnt−a−c b+cntac

所以实际上就是求出最大的子段和。
题解参考与博客

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
const int maxn = 1e6 + 10;
char s[maxn];
int main() {
    int t;
    read(t);
    while (t--) {
        int n, k, cnt = 0, Max = 0;
        read(n), read(k);
        scanf("%s", s);
        int len = strlen(s);
        for (int i = 0; i < len; i++) cnt += s[i] - '0';
        for (int i = 0; i < k; i++) {
            int cur = 0, x = 0;
            for (int j = i; j < n; j += k) {
                if (s[j] == '0') x = -1;
                else x = 1;
                cur += x;
                if (cur < 0) cur = 0;
                Max = max(cur, Max);
            }
        }
        out(cnt - Max);
        putchar('\n');
    }
    return 0;
}

你可能感兴趣的:(codeforces)