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

……啊开始颓了。c++

【题目大意】app

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

【思路】code

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

【错误点】队列

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

 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 }
相关文章
相关标签/搜索