~~~题面~~~

题解:

首先我们要使得Miss的次数尽量少,也就是要尽量保证每个点在被访问的时候,这个点已经存在于Cache中。

那么我们可以得到一个结论:

如果Cache已满,那么我们就从Cache里面取出下一个出现位置最远的那个数(如果不出现了那么令下一个出现位置为inf)

所以用堆维护即可。

我们记录一个Next[i],表示s[i]后面再次遇到s[i]的位置是哪,如果当前的s[i]就是最后一个s[i],那么Next[i] = inf

值得注意的是,遇到相同元素时我们并不需要从堆中删除上一个数然后再塞入当前数,因为这将不会对操作产生影响。而且要强行删除的话要重建整个堆,时间复杂度承受不来。。。

为什么不会有影响?

注意到对于相同元素而言,Next[i]是递增的

即Next[i] < Next[Next[i]] < Next[Next[Next[i]]]

而遇到相同元素就代表遇到了Next[i],所以塞入这个数后,上一个数虽然没有被删除,但被这个数覆盖了,每次取出肯定是优先这个数的

(为什么突然觉得有点不太严谨。。。。那为了保险的话就在取数的时候判断一下就好了)

 // luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 100100
#define inf 10000000
int n, m, tot, cnt, ans;
int s[AC], last[AC], w[AC], Next[AC];
bool z[AC]; struct cmp{
bool operator () (int a, int b)
{
return Next[a] < Next[b];
}
}; priority_queue<int, vector<int>, cmp> q; inline int read()
{
int x = ; char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline bool cmp(int a, int b)
{
return a < b;
} int half(int x)//二分离散化后的编号
{
int l = , r = tot, mid;
while(l < r)
{
mid = (l + r) >> ;
if(w[mid] < x) l = mid + ;
else if(w[mid] > x) r = mid - ;
else if(w[mid] == x) return mid;
}
return l;
} void pre()
{
int x;
n = read(), m = read();
for(R i = ; i <= n; i++) s[i] = w[i] = read();
sort(w + , w + n + , cmp);
for(R i = ; i <= n; i++)
if(w[i] != w[i+]) w[++tot] = w[i];
for(R i = ; i <= n; i++)
{
x = half(s[i]);
if(last[x]) Next[last[x]] = i;//建立一个单向的连接
last[x] = i;//记录上一个出现的x的位置
}
for(R i = ; i <= n; i++)
if(!Next[i]) Next[i] = inf;
}//最后一个的Next为inf(最优先弹出) void work()
{//因为要弹出的是最远的,而之前的相比之后的必然要近一些(同一个数字),而且每次被迫弹出后都必然会塞入一个更远的,
int x, id;//所以之前那些东西放在堆里其实也没关系,不会对答案产生影响
for(int i = ; i <= n; i++)
{
id = half(s[i]);//获取编号
if(z[id])
{
q.push(i);
continue;//如果已经有了,,,那也要赛进去,,,表示替换对应的Next,但不能计入ans
}//因为不删去旧元素并不会造成影响,因此还是可以视作q内没有重复元素的
else if(cnt < m) //如果还没有满
{
++cnt, ++ans;
q.push(i);
z[id] = true;
}
else
{
x = q.top();
x = half(s[x]);//存的是编号
z[x] = false;//已经弹出了
q.pop();
q.push(i);
z[id] = true;
++ans;
}
}
printf("%d\n", ans);
} int main()
{
//freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}

[JSOI2010]缓存交换 贪心 & 堆的更多相关文章

  1. B1826 [JSOI2010]缓存交换 贪心+离散化+堆

    这个题仔细一想可以直接贪心做,因为队列里下一个出现的早的一定最优.正确性显然.然后我只拿了50,我直接模拟另一个队列暴力修改最后一个点的nxt值,自然会T.但是其实不用修改,直接插入就行了前面的不影响 ...

  2. 【BZOJ1826】[JSOI2010]缓存交换(贪心)

    [BZOJ1826][JSOI2010]缓存交换(贪心) 题面 BZOJ 洛谷 题解 当缓存不满显然直接放进去,满了之后考虑拿走哪一个.不难发现拿走下一次出现时间最晚的那个一定不会更差. 那么用一个堆 ...

  3. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

  4. 1826: [JSOI2010]缓存交换

    1826: [JSOI2010]缓存交换 https://www.lydsy.com/JudgeOnline/problem.php?id=1826 分析: 简单的贪心,然后调啊调...最近怎么了,码 ...

  5. bzoj1528[POI2005]sam-Toy Cars*&&bzoj1826[JSOI2010]缓存交换

    bzoj1528[POI2005]sam-Toy Cars bzoj1826[JSOI2010]缓存交换 题意: Jasio有n个不同的玩具,它们都被放在了很高的架子上,地板上不会有超过k个玩具.当J ...

  6. BZOJ1826 [JSOI2010]缓存交换 堆 贪心

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1826 题意概括 Cache中有m个储存单元,接下来有n个访问地址,每个地址用一个数字表示.访问每一 ...

  7. [bzoj1826] [JSOI2010]缓存交换

    虽然不知道为什么..但显然,每次扔掉离下次查询最远的内存单元就行了233 用堆来维护贪心...(优先队列大法好 #include<cstdio> #include<iostream& ...

  8. JSOI2010 缓存交换

    题目链接:戳我 考虑一个贪心--就是每次我们都选择队列里面之后最晚加入的元素弹出. 维护一个nxt数组就行了. 特判一下之后不会再加入的元素. 代码如下: #include<iostream&g ...

  9. Luogu P4404 [JSOI2010]缓存交换 优先队列

    细节题?...调了半天.... 可以发现,每一次从缓存中删除的主存一定是下次访问最晚的,可以用优先队列来处理...还有要离散化...还有链表末尾要多建一些点...否则会死的很惨... #include ...

随机推荐

  1. springboot 配置二级缓存

    springBoot中配置mybatis的二级缓存 2018年01月22日 11:45:37 Ting.Xue(Martin.Xue) 阅读数:5604更多 个人分类: SSM的Spring框架Myb ...

  2. Linux怎样创建FTP服务器--修改用户默认目录-完美解决 - 费元星

    在创建FTP服务器之有先命令: ps -ef |grep vsftpd 查一下系统有没有安装vsftpd这个服务器,如果出现如下图所示的界面说明没有安装.   然后再执行:yum install vs ...

  3. Maxscript-获取选中文件

    Maxscript - 获取选中文件 使用 .Net 的方法弹出窗口选择文件,并范围所有选中文件的路径“” Fn Fun_GetFilePaths strTitle strFilter = ( dia ...

  4. 一句话描述 Java 设计模式

    Java 设计模式 设计模式是对应于不同的应用目的的.   适配:将特定功能接口适配需求方   桥接:面向两个接口,无关接口的实现: 抽象化与实现化解耦,使得二者可以独立变化:例:笔与图形,笔可以画图 ...

  5. [SHELL]结构化命令之条件语句

    1.if-then语句  #!/bin/bash username="root" if grep $username /etc/passwd then echo "the ...

  6. 凸包算法(Graham扫描法)详解

    先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明  p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...

  7. [CH0304]IncDec Sequence

    和NOIP2018DAY1T1类似的题目,但思维难度高多了. 这题既可以抬高路面,也可以降低路面,而且目标平面不确定,就难起来了. 但是两道题的基本思路几乎一样,同样我们将 2~n 的高度差分,1之所 ...

  8. [HNOI2018]转盘

    [HNOI2018]转盘 给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 ...

  9. php 安全方面面试题

    1 MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化? a. 设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率.b. 选择合适的表字段数据类型和存储 ...

  10. Python3.5在Windows7环境下Scrapy库的安装

    Python3.5在Windows7环境下Scrapy库的安装 忙活了一下午,总算是把Scrapy库给装完了,记下来给需要帮助的人 首先安装的环境:Windows7 64位 Python的版本是:3. ...