USACO19JAN Redistricting

题目链接:戳我

一个优先队列优化DP

一定要注意第二关键字的排序啊!!我真的是菜,被坑了好久qwq
\(f[i]\)表示前i个的最小答案,从前面选择的时候第一关键字是f[j]的大小,第二关键字是要确保[j+1,i]区间产生的贡献尽可能小

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define MAXN 300010
using namespace std;
int n,k;
int f[MAXN],sum[MAXN];
struct Node
{
    int pos,f;
    friend bool operator < (Node x,Node y)
    {
        if(x.f==y.f) return sum[x.pos]>sum[y.pos];
        return x.f>y.f;}
};
priority_queue<Node>q;
char s[MAXN];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    // freopen("ce.out","w",stdout);
    #endif
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='H') sum[i]=sum[i-1]+1;
        else sum[i]=sum[i-1]-1;
    }
    // for(int i=1;i<=n;i++) printf("sum[%d]=%d\n",i,sum[i]);
    q.push((Node){0,0});
    for(int i=1;i<=n;i++)
    {
        while(!q.empty()&&q.top().pos<i-k) q.pop();
        Node cur;
        int cur_ans;
        if(sum[i]-sum[q.top().pos]<=0) cur_ans=1;
        else cur_ans=0;
        cur.f=q.top().f+cur_ans;
        f[i]=cur.f;
        cur.pos=i;
        // printf("i=%d f=%d top_pos=%d\n",i,cur.f,q.top().pos);
        q.push(cur);
    }
    printf("%d\n",f[n]);
    return 0;
}
posted @ 2019-06-19 17:52  风浔凌  阅读(194)  评论(0编辑  收藏  举报