LRU (二分)

LRU

题目链接

题意 :
(吐槽计算机组成原理)计算机内存分块构成,由1 − n编号。现在要求求缓存的块数,使得对于给定的长度为n 的请求序列,少k 次命中缓存。其中,在命中缓存时有三种情况:

1.缓存中存在当前请求编号的块,此时命中该编号的缓存;
2.未命中缓存,缓存未满,当前块写入缓存;
3.未命中缓存,缓存已满,替换缓存中时间最久的块;
思路 :
二分一个长度并进行检验,检验时用一个s e t 维护Cache中的块编号,并按照请求序列的先后顺序进行排序,用一个m a p维护映射元素上一次的出现位置。
对于命中缓存的情况,先擦除上次的数据,再保存本次的编号;
对于缓存已满的情况,则擦除set中的第一个元素(历史最久远的块),然后插入新块;
缓存未满,直接插入新块。
有一个技巧,在插入元素时不要使用insert,而是使用emplace方法,避免插入时多余的一次构造和析构,可以提升程序效率。

AC代码 :

#include <iostream>
#include <unordered_map>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <set>

#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
using namespace std;

const int N = 1e5 + 10;
int a[N];

struct node {
    int idx, val;
    bool operator<(const node& a) const { return idx < a.idx; }
};

bool check(int x, int n, int k){
    set<node> se;
    unordered_map<int, int> mp;
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
        if (mp.count(a[i])) {
            ++cnt;
            se.erase({mp[a[i]], a[i]});
            se.insert({i, a[i]});
            mp[a[i]] = i;
            continue;
        } 
        if (se.size() == x) {
            node top = *se.begin();
            se.erase(se.begin());
            mp.erase(top.val);
        }
        mp[a[i]] = i;
        se.emplace(node{i, a[i]});
    }
    return cnt >= k;
}

signed main(){
	IOS;
    int n, k; cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int l = 1, r = n + 1, ans = -1;
    while(l <= r){
        int mid = l + r >> 1;
        if(check(mid, n, k)) r = mid - 1, ans = mid;
        else l = mid + 1;
    }
    if(ans < 0) puts("cbddl");
    else printf("%lld\n", ans);
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值