[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; }