Description
Input
Output
输出更赛牛较多的或者均势的分区的最小可能数量。
Sample Input
7 2
HGHGGHG
Sample Output
3
题意:
给你一个串,让你把它分成若干个块,每个块的最大长度为k,问你最后H的数量<=G的数量的块最少的可能是多少。
题解:
这道题一看就是dp,由于它的数据是1e5,那么就不太可能是状压和区间了,那么就是普通dp。dp[i]保存的是在第i个点G的数量>=H的数量的划分的最小区间个数。普通dp有一个特点:后面的状态从前面的状态转移过来。那么这道题到第i个点可以由max(0,i-k)到i-1这个区间的值转移过来,那么由哪里转移过来?肯定是最小值了,否则就不会是最优解。但是最小值有可能有多个,举个例子:
9 6
GGGGGGHGH
这种情况,刚开始六个G都是1,后面的第一个H由于能比前面的任何一个大,所以还是1,之后的G,由于前面的H并没有比它多,所以就变成2了,那么到现在为止dp数组是1 1 1 1 1 1 1 2 0,到最后一个数我们改取什么?肯定是HGH最后3个数,这样就可以消掉一个区间,那么我们要取的是前面G-H最大的那个位置。这样的话后面的H-G会最大,那么优先队列就这样排序就好了。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
char s[N];
int g[N],h[N],dp[N];
struct node
{
int val,del,id;
bool operator< (const node& a)const
{
if(val!=a.val)
return val>a.val;
return del<a.del;
}
};
int main()
{
int n,k;
scanf("%d%d",&n,&k);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
g[i]=g[i-1]+(s[i]=='G'),h[i]=h[i-1]+(s[i]=='H'),dp[i]=1e9;
dp[0]=0;
priority_queue<node>Q;
Q.push({0,0,0});
for(int i=1;i<=n;i++)
{
int sta;
if(i<k)
sta=0;
else
sta=i-k;
while(Q.top().id<sta)
Q.pop();
node t;
t=Q.top();
dp[i]=t.val+(g[i]-g[t.id]>=h[i]-h[t.id]);
Q.push({dp[i],g[i]-h[i],i});
}
printf("%d\n",dp[n]);
return 0;
}