2021 ICPC 江西省大学生程序设计竞赛 J.LRU 二分

108 篇文章 1 订阅
5 篇文章 0 订阅

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

  1. 缓存中存在当前请求编号的块,此时命中该编号的缓存;
  2. 未命中缓存,缓存未满,当前块写入缓存;
  3. 未命中缓存,缓存已满,替换缓存中时间最久的块;

思路:二分一个长度并进行检验,检验时用一个 s e t set set维护 C a c h e Cache Cache中的块编号,并按照请求序列的先后顺序进行排序,用一个 m a p map map维护映射元素上一次的出现位置。

  1. 对于命中缓存的情况,先擦除上次的数据,再保存本次的编号;
  2. 对于缓存已满的情况,则擦除 s e t set set中的第一个元素(历史最久远的块),然后插入新块;
  3. 缓存未满,直接插入新块。

有一个技巧,在插入元素时不要使用 i n s e r t insert insert,而是使用 e m p l a c e emplace emplace方法,避免插入时多余的一次构造和析构,可以提升程序效率。

#include <bits/stdc++.h>
#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; }
};

inline 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(){
    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HeartFireY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值