[JSOI2010]缓存交换 贪心 & 堆
题解:
首先我们要使得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]缓存交换 贪心 & 堆的更多相关文章
- B1826 [JSOI2010]缓存交换 贪心+离散化+堆
这个题仔细一想可以直接贪心做,因为队列里下一个出现的早的一定最优.正确性显然.然后我只拿了50,我直接模拟另一个队列暴力修改最后一个点的nxt值,自然会T.但是其实不用修改,直接插入就行了前面的不影响 ...
- 【BZOJ1826】[JSOI2010]缓存交换(贪心)
[BZOJ1826][JSOI2010]缓存交换(贪心) 题面 BZOJ 洛谷 题解 当缓存不满显然直接放进去,满了之后考虑拿走哪一个.不难发现拿走下一次出现时间最晚的那个一定不会更差. 那么用一个堆 ...
- BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心
BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...
- 1826: [JSOI2010]缓存交换
1826: [JSOI2010]缓存交换 https://www.lydsy.com/JudgeOnline/problem.php?id=1826 分析: 简单的贪心,然后调啊调...最近怎么了,码 ...
- bzoj1528[POI2005]sam-Toy Cars*&&bzoj1826[JSOI2010]缓存交换
bzoj1528[POI2005]sam-Toy Cars bzoj1826[JSOI2010]缓存交换 题意: Jasio有n个不同的玩具,它们都被放在了很高的架子上,地板上不会有超过k个玩具.当J ...
- BZOJ1826 [JSOI2010]缓存交换 堆 贪心
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1826 题意概括 Cache中有m个储存单元,接下来有n个访问地址,每个地址用一个数字表示.访问每一 ...
- [bzoj1826] [JSOI2010]缓存交换
虽然不知道为什么..但显然,每次扔掉离下次查询最远的内存单元就行了233 用堆来维护贪心...(优先队列大法好 #include<cstdio> #include<iostream& ...
- JSOI2010 缓存交换
题目链接:戳我 考虑一个贪心--就是每次我们都选择队列里面之后最晚加入的元素弹出. 维护一个nxt数组就行了. 特判一下之后不会再加入的元素. 代码如下: #include<iostream&g ...
- Luogu P4404 [JSOI2010]缓存交换 优先队列
细节题?...调了半天.... 可以发现,每一次从缓存中删除的主存一定是下次访问最晚的,可以用优先队列来处理...还有要离散化...还有链表末尾要多建一些点...否则会死的很惨... #include ...
随机推荐
- cakephp1.3中help form的一个小问题
如果我们在模版里这么干 <?php echo $form->input('last_sold_date',array('autocomplete'=>'off','label'=&g ...
- Vue框架核心之数据劫持
本文来自网易云社区. 前瞻 当前前端界空前繁荣,各种框架横空出世,包括各类mvvm框架横行霸道,比如Angular.Regular.Vue.React等等,它们最大的优点就是可以实现数据绑定,再也不需 ...
- 三个线程ABC,交替打印ABC
转载与:https://www.cnblogs.com/x_wukong/p/4009709.html 创建3个线程,让其交替打印ABC . 输出如下: ABCABCABCABC. 方法:使用syn ...
- ArrayList与LinkedList的普通for循环遍历
对于大部分Java程序员朋友们来说,可能平时使用得最多的List就是ArrayList,对于ArrayList的遍历,一般用如下写法: public static void main(String[] ...
- 默认初始化&拷贝初始化&直接初始化&值初始化&列表初始化
一.各种初始化的形式 /* 定义变量形式一:不指定初始值 */ int a; // 默认初始化 /* 定义变量形式二:指定初始值 */ int b = 1; // 拷贝初始化 int b(1); // ...
- 域名加www与不加www不一样结果的解决办法
有些浏览器域名访问加www 与不加www出现的页面不一样.在aj请求的时候也不同.firefox与google新版本的都会自动加上www. 比如 访问haitaohua.com,但aj请求的时候是带w ...
- encode 与 decode
decode 将其它编码的字符串转换成unicode编码,例如:str1.decode("gb2312"),表示将gb2312编码的字符串转换成unicode编码 encode 将 ...
- Calculation PartⅡ
GitHub/object-oriented 误删内容--周末修复
- Uncaught Error: Syntax error, unrecognized expression: |117的js错误
117指的是js代码在浏览器运行时的出错的行号 var a="117|117" 前面的错误是由于有特殊符号“|”,用$("txtId"+a).val();去取 ...
- Java之comparable接口
comparable 接口: 1. 问题:java.util.Collections 类中的方法 Collections.sort(List list) 是根据什么确定容器中对象的“大小”顺序的? 2 ...