​题目链接​题意: 给出你长度为CF687 D2 C. Bouncing Ball(DP)_i++的一个序列,你需要从第CF687 D2 C. Bouncing Ball(DP)_#include_02个开始计算,周期是CF687 D2 C. Bouncing Ball(DP)_#include_03(每隔CF687 D2 C. Bouncing Ball(DP)_#include_03个取一次),你想每次取的都是CF687 D2 C. Bouncing Ball(DP)_#define_05

  1. 变换,将一个位置为0的转化成1花费CF687 D2 C. Bouncing Ball(DP)_#include_06代价
  2. 删除第一个,删除是否整体前移一位,代价是CF687 D2 C. Bouncing Ball(DP)_#include_07

题解: 
我是fw就是从后往前看是否需要变换,然后从前往后看删除前面的数代价大还是不删除代价大.
简单的说就是,两种方式 变换与删除,表示就OK了。
变换:因为我们是从前往后删数,所以后面的相对不变化所以我们就需要维护这个相对不变化的。就像前缀和一样维护出来。以达到取数取的都还是1
删除:我们是从前往后删,那么就是看从那个地方开始更优。

#include <bits/stdc++.h>
#define
using namespace std;
const int N = 2e5;
ll T, n, p, k, x, y;
bool a[N];
ll sum[N];
inline ll read() {
ll tot = 0, f = 1; char c = getchar ();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar (); }
while (c >= '0' && c <= '9') { tot = tot * 10 + c - '0'; c = getchar (); }
return tot * f;
}
int main(){
T = read();
while (T--) {
memset (sum, 0, sizeof (sum));
ll ans = 0x3f3f3f3f;
n = read (); p = read (); k = read ();
char ch[N]; cin >> ch + 1;
for (ll i = 1; i <= n; i++) a[i] = ch[i] - '0';///找到没个点的代价
x = read (); y = read ();
for (ll i = n; i >= 1; i--) {
sum[i] = sum[i + k] + (a[i] == 0 ? 1: 0) * x;///从后往前枚举是否需要换数
}
for (ll i = 0; i <= n - p; i++) {
ans = min(ans, i * y + sum[p + i]);///从前往后枚举 是否删数
}
printf ("%lld\n", ans);
}
return 0;
}