/*
贪心,优先队列
首先这个贪心啊,每次删除下次最晚再玩的玩具,要维护next表示下次的位置。然后优先队列。
这样这个玩具这段时间内不会对答案有贡献,且时间最长。
开始想成了每次删除使用总数最少的玩具,发现这个反例大大的有,还不好写。
然后就是代码,问题来自于如何维护已经在队列里的玩具的next
可以每次碰到在队列里的的玩具时把k扩大1,把这个玩具再次放到优先队列。
此时这个玩具的next一定比已经在队列里的这个玩具的next大(好拗口)。
这样就起到了更新next的效果。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 500001
using namespace std;
int n,m,k,ans;
int cnt[N],c[N],Last[N];
bool vis[N];
struct node{
int num,nxt;
friend bool operator < (node x,node y)
{
return x.nxt<y.nxt;
}
}a[N];
priority_queue<node>q;
int main()
{
scanf("%d%d%d",&n,&k,&m);
for(int i=1;i<=m;i++)
scanf("%d",&a[i].num);
for(int i=1;i<=n;i++) Last[i]=m+1;
for(int i=m;i>=1;i--)
a[i].nxt=Last[a[i].num],Last[a[i].num]=i;
for(int i=1;i<=m;i++)
{
if(vis[a[i].num]){k++;q.push(a[i]); continue;}
else
{
if(q.size()==k)
{
node x=q.top();q.pop();
vis[x.num]=0;
}
q.push(a[i]);
ans++;vis[a[i].num]=1;
}
}
printf("%d\n",ans);
return 0;
}
bzoj1528 sam-Toy Cars(贪心,优先队列)
原文:https://www.cnblogs.com/L-Memory/p/9748114.html