【優先隊列+貪心】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 }
相關文章
相關標籤/搜索