【优先队列+贪心】BZOJ1826-[JSOI2010]缓存交换

……啊开始颓了。

【题目大意】

已知当前集合最大容量为m,n个询问。每次询问一个元素,如果集合中没有则需要加入该元素,如果集合已经满了则需要先删去集合中的某些元素再加入。问至少要加入几次元素?

【思路】

显然每一次删除的元素是下一次出现最晚的那一个,优先队列维护一下就好了。

【错误点】

非常ZZ地把集合满的条件定为了“que.size()==m”,实际上如果该元素已经存在,我们更新下一次出现的时候原来的在优先队列中是不删除的。所以必须另外设一个qsize记录集合中有几个元素存在。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=110000;
 4 typedef pair<int,int> p;
 5 const int INF=0x7fffffff;
 6 int n,m,a[MAXN],d,hash[MAXN];
 7 int rcap[MAXN],nap[MAXN];//recently appear & next appear
 8 priority_queue<p> que;
 9 int inque[MAXN],qsize;
10 
11 void init()
12 {
13     scanf("%d%d",&n,&m);
14     for (int i=1;i<=n;i++) scanf("%d",&a[i]),hash[i]=a[i];
15     sort(hash+1,hash+n+1);
16     d=unique(hash+1,hash+n+1)-(hash+1);
17     for (int i=1;i<=n;i++) a[i]=lower_bound(hash+1,hash+d+1,a[i])-hash;
18     for (int i=1;i<=n;i++) rcap[i]=nap[i]=INF;
19     for (int i=1;i<=n;i++)
20     {
21         if (rcap[a[i]]!=INF) nap[rcap[a[i]]]=i;
22         rcap[a[i]]=i;
23     }
24 } 
25 
26 void solve()
27 {
28     int ans=0;
29     memset(inque,0,sizeof(inque));
30     qsize=0;
31     for (int i=1;i<=n;i++)
32     {
33         if (!inque[a[i]])
34         {
35             if (qsize==m) //这里不能用que.size()代替,因为相同元素可能都在优先队列里呢 
36             {
37                 inque[que.top().second]=0;
38                 que.pop();
39                 qsize--;
40             }
41             inque[a[i]]=1;
42             ans++;
43             qsize++;
44         }
45         que.push(p(nap[i],a[i]));
46     }
47     printf("%d\n",ans);
48 }
49 
50 int main()
51 {
52     init();
53     solve();
54     return 0;
55 }

 

转载于:https://www.cnblogs.com/iiyiyi/p/6066585.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值