[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 ...
随机推荐
- 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)
什么是GCM? Google Cloud Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...
- Python对象引用问题总结
对于对象引用问题,一直是一知半解的状态,现整理以备使用. 操作不可变对象进行加减运算时,会在内存中创建新的不可变实例,不会影响原来的引用>>> c=12>>> d= ...
- 惊喜Skr人,Istio的创始人Shriram Rajagopalan手把手教你如何使用Istio
Shriram与来自Google.Lyft.IBM和其他公司的社区贡献者们一起并肩作战,积极地向Istio和Envoy项目作贡献.同时,Shriram是IBM的Amalgam8项目的创始成员之一.目前 ...
- jmeter 函数助手
1.选项,函数助手对话框,打开函数助手 2.使用方法 输入参数,点击生成,可以直接使用(Name of variable in which to store the result (optional) ...
- MySQL三方面优化
第一方面:30种mysql优化sql语句查询的方法1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用 ...
- 打印队列 (Printer Queue,ACM/ICPC NWERC 2006,UVA12100)
题目描述: 题目思路: 使用一个队列记录数字,一个优先队列记录优先级,如果相等即可打印: #include <iostream> #include <queue> using ...
- [译] JavaScript核心指南(JavaScript Core) 【转】
本文转自:http://remember2015.info/blog/?p=141#scope-chain 零.索引 对象(An Object) 原型链(A Prototype Chain) 构造函数 ...
- [leetcode-676-Implement Magic Dictionary]
Implement a magic directory with buildDict, and search methods. For the method buildDict, you'll be ...
- HDU 4169 Wealthy Family(树形DP)
Problem Description While studying the history of royal families, you want to know how wealthy each ...
- defineporperty 的使用 设置对象的只读或只写属性
<!DOCTYPE html> <html lang="en"> <head> <title>Document</title& ...