Cooking Time

Cooking Time 

 

 

 

 题意: 有n种调料放在冰箱,你最多能把k种调料放外面,你每次打开冰箱,可以拿出一种调料,同时也可以放回去一种调料,也可以不放回。 每组输入案例第一行为n,k,第二行为n种调料的编号(从1到1e9),需要调料的顺序是输入的循序,输出是最少要打开多少次。

对于知道使用情况的置换算法,最优解是找一个最后需要使用的物品替换掉也就是,如果一个物品后面已经不需要用到,就要放回去了,当外面的物品达到了k个,此时某些情况我就得从外面中拿一个回去

思路:
离散化:看到a[i]比较大,而个数比较少,并且只需要知道相对编号就好,这时就想到了离散化
next数组下一个相同值在哪个位置;
last数组用来辅助next数组记录,一开始所有的last[a[i]]==inf,只要大于a[i]编号(a[i]的编号通过离散化只会最大从0~(n-1))就好了,所以这里我用了last[a[i]]=n;
inqueue数组用来判断是否物品在外面(即在队列中)
具体细节见代码

AC_Code

 1 #include <cstring>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <bits/stdc++.h>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=1e5+5;
10 int a[maxn],b[maxn],nxt[maxn],last[maxn],inqueue[maxn];
11 
12 map<int,int>mp;
13 struct node{
14     int nxt,id;
15     bool operator < (const node &rhs ) const {
16         return nxt<rhs.nxt;         //按下一次需要的"时间"从大到小排序
17     }
18 };
19 
20 int main()
21 {
22     int t,n,k,ans;
23     scanf("%d",&t);
24     while( t-- ){
25         ans=0;
26         priority_queue<node>Q;
27         memset(inqueue,0,sizeof(inqueue));
28         mp.clear();
29 
30         int cnt=0;
31         scanf("%d%d",&n,&k);
32 //        for(int i=0;i<n;i++){       //离散化
33 //            scanf("%d",&a[i]);
34 //            if( !mp.count(a[i])){
35 //                mp[a[i]]=cnt++;
36 //            }
37 //            a[i]=mp[a[i]];
38 //            last[a[i]]=n;
39 //        }
40 
41         for(int i=0;i<n;i++){       //这种离散化方式更快
42             scanf("%d",&a[i]);
43             b[i]=a[i];
44         }
45         sort(b,b+n);
46         int reu=unique(b,b+n)-b;
47         for(int i=0;i<n;i++){
48             a[i]=lower_bound(b,b+reu,a[i])-b;
49             last[a[i]]=n;
50         }
51         for(int i=n-1;i>=0;i--){    //设定next
52             nxt[i]=last[a[i]];
53             last[a[i]]=i;
54         }
55 
56         for(int i=0;i<n;i++){
57             if(inqueue[a[i]]){            //如果要拿出的物品已经外面有了,那就把这个也压入队列,
58                                           //因为next值发生了变化,也要更新。这是a[i]最新的next值
59                 Q.push((node){nxt[i],a[i]});
60                 continue;
61             }
62             else if( k ){                //在外面的物品不够,直接拿出来
63                 Q.push((node){nxt[i],a[i]});
64                 inqueue[a[i]]=1;
65                 k--;
66                 ans++;
67             }
68             else{                       //在外面的物品够了,则要进行放进去,拿出来的操作
69                 node x=Q.top();
70                 Q.pop();
71                 inqueue[x.id]=0;
72                 Q.push((node){nxt[i],a[i]});
73                 inqueue[a[i]]=1;
74                 ans++;
75             }
76         }
77         printf("%d\n",ans);
78     }
79     return 0;
80 }

 

posted @ 2020-02-06 17:14  swsyya  阅读(272)  评论(0编辑  收藏  举报

回到顶部