[POI2005]SAM-Toy Cars

[POI2005]SAM-Toy Cars

题意:

好像题意已经挺明白的了,戳。

解法:

首先来想一下如何才能尽量少的取玩具. 显然,如果一个玩具已经在地上了,就可以不用去取. 但是地上能放的玩具的数量有限,所以我们可以记录每种玩具下一次要被玩的时间next[i],并在需要更换玩具的时候换走当前队列中next[i]最大的那一个玩具.
所以我们可以得到这样一个贪心策略:要换玩具的时候,换next[i]最远的那个玩具。
然后就是模拟一下入队出队情况,用优先队列维护一下next。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

#define LL long long
#define N 500010
#define M 100010

int n,k,p,a[N];
int nxt[N],ans;
bool vis[M];

struct cmp {
    inline bool operator() (const int &a,const int &b) {
        return nxt[a] < nxt[b];
    }
};
queue <int> q1[M];
priority_queue <int,vector<int>,cmp> q2;

int main() {
    scanf("%d%d%d",&n,&k,&p);
    for(int i = 1 ; i <= p ; i++) {
        scanf("%d",&a[i]);
        q1[a[i]].push(i);
    }
    for(int i = 1 ; i <= p ; i++) {
        q1[a[i]].pop();
        if(q1[a[i]].empty()) nxt[i] = p + 1;
        else nxt[i] = q1[a[i]].front();
    }
    for(int i = 1 ; i <= p ; i++) {
        if(!vis[a[i]]) {
            if(q2.size() == k) {
                vis[a[q2.top()]] = 0;
                q2.pop();
            }
            q2.push(i); 
            vis[a[i]] = 1; 
            ans++;
        }
        else q2.push(i), k++;
    }
    printf("%d \n",ans);
    //system("pause");
    return 0;
}
posted @ 2019-08-25 21:08  西窗夜雨  阅读(165)  评论(0编辑  收藏  举报