要想判断2种奶牛在一段区间内的数差,自然想到用前缀和。dp式也容易想出。
dp[i] = min(dp[i - j] + (pre[i] - pre[i - j] >= 0 ? 1 : 0)); (1<=j<=k)
然而会超时。考虑到pre数组对答案的贡献只可能为1或0,我们可以先考虑dp数组的min值。我们可以用队列维护。与此同时,我们要考虑pre值排在前面的要大,这样G奶牛越不可能占优势。
#include<cstdio>
#include<queue>
using namespace std;
const int N = 300002;
int n, k, pre[N], dp[N];
struct node {
int num, id;
bool operator < (const node &t) const {
if(num == t.num)
return pre[id] < pre[t.id];
return num > t.num;
}
};
priority_queue <node> q;
int main() {
char ch;
scanf("%d %d", &n, &k);
scanf("\n");
for(int i = 1; i <= n; i ++) {
ch = getchar();
if(ch == 'G')
pre[i] = pre[i - 1] + 1;
else
pre[i] = pre[i - 1] - 1;
}
q.push((node) {0, 0});
for(int i = 1; i <= n; i ++) {
while(q.top().id < i - k)//求的是前缀和,应为真实下标-1
q.pop();
dp[i] = (pre[i] >= pre[q.top().id]) ? q.top().num + 1 : q.top().num;
q.push((node) {dp[i], i});
}
printf("%d\n", dp[n]);
return 0;
}
PS:一定记得先push一个值哦,不然队列会空。
如有错误,请大佬在评论区指出。谢谢!