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

Description

在计算机中,CPU只能和高速缓存Cache直接交换数据。当所需的内存单元不在Cache中时,则需要从主存里把数据调入Cache。此时,如果Cache容量已满,则必须先从中删除一个。 例如,当前Cache容量为3,且已经有编号为10和20的主存单元。 此时,CPU访问编号为10的主存单元,Cache命中。 接着,CPU访问编号为21的主存单元,那么只需将该主存单元移入Cache中,造成一次缺失(Cache Miss)。 接着,CPU访问编号为31的主存单元,则必须从Cache中换出一块,才能将编号为31的主存单元移入Cache,假设我们移出了编号为10的主存单元。 接着,CPU再次访问编号为10的主存单元,则又引起了一次缺失。我们看到,如果在上一次删除时,删除其他的单元,则可以避免本次访问的缺失。 在现代计算机中,往往采用LRU(最近最少使用)的算法来进行Cache调度——可是,从上一个例子就能看出,这并不是最优的算法。 对于一个固定容量的空Cache和连续的若干主存访问请求,聪聪想知道如何在每次Cache缺失时换出正确的主存单元,以达到最少的Cache缺失次数。

Input

输入文件第一行包含两个整数N和M(1<=M<=N<=100,000),分别代表了主存访问的次数和Cache的容量。 第二行包含了N个空格分开的正整数,按访问请求先后顺序给出了每个主存块的编号(不超过1,000,000,000)。

Output

输出一行,为Cache缺失次数的最小值。

Sample Input

6 2
1 2 3 1 2 3

Sample Output

4

HINT

在第4次缺失时将3号单元换出Cache。


考虑x数某次出现的位置到它下一次出现的位置这段区间。

如果我想要让x不缺失,需要在这段区间里让x进入cache,相当于在这个区间(左开右开)塞一个数。

那么整个序列中,每个位置中最多能塞入m-1个数,因为x这个数已经在cache里了。

然后就变成了另一道题:http://www.cnblogs.com/suika/p/8711400.html

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 200050
#define ls p<<1
#define rs p<<1|1
int n,m;
int t[N<<2],add[N<<2],now[N],tot;
struct A {
int num,id,v;
}a[N];
struct node {
int l,r;
}b[N];
bool cmp1(const A &x,const A &y){return x.num<y.num;}
bool cmp2(const A &x,const A &y){return x.id<y.id;}
bool cmp3(const node &x,const node &y) {
if(x.r==y.r) return x.l>y.l;
return x.r<y.r;
}
void pushdown(int p) {
if(add[p]) {
int d=add[p];
add[ls]+=d; t[ls]+=d;
add[rs]+=d; t[rs]+=d;
add[p]=0;
}
}
void build(int l,int r,int p) {
t[p]=m-1;
if(l==r) {return ;}
int mid=(l+r)>>1;
build(l,mid,ls); build(mid+1,r,rs);
}
int query(int l,int r,int x,int y,int p) {
if(x<=l&&y>=r) return t[p];
int mid=(l+r)>>1,re=1<<30;
pushdown(p);
if(x<=mid) re=min(re,query(l,mid,x,y,ls));
if(y>mid) re=min(re,query(mid+1,r,x,y,rs));
t[p]=min(t[ls],t[rs]);
return re;
}
void update(int l,int r,int x,int y,int v,int p) {
if(x<=l&&y>=r) {
t[p]+=v; add[p]+=v;
return ;
}
pushdown(p);
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,y,v,ls);
if(y>mid) update(mid+1,r,x,y,v,rs);
t[p]=min(t[ls],t[rs]);
}
int main() {
memset(t,0x3f,sizeof(t));
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++) {
scanf("%d",&a[i].num); a[i].id=i;
}
sort(a+1,a+n+1,cmp1);
int j=0;a[0].num=1<<30;
for(i=1;i<=n;i++) {
if(a[i].num!=a[i-1].num)j++;
a[i].v=j;
}
sort(a+1,a+n+1,cmp2);
int ans=n;
for(i=n;i>=1;i--) {
if(now[a[i].v]) {
b[++tot].l=i+1;
b[tot].r=now[a[i].v]-1;
if(b[tot].l>b[tot].r) tot--,ans--;
}
now[a[i].v]=i;
}
sort(b+1,b+tot+1,cmp3);
build(1,n,1);
for(i=1;i<=tot;i++) {
int re=query(1,n,b[i].l,b[i].r,1);
if(re>=1) {
update(1,n,b[i].l,b[i].r,-1,1);
ans--;
}
}
printf("%d\n",ans);
}

BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心的更多相关文章

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

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

  2. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  3. BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

    BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树 Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数 ...

  4. 1826: [JSOI2010]缓存交换

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

  5. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  6. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  7. BZOJ_2124_等差子序列_线段树+Hash

    BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...

  8. BZOJ_1798_[AHOI2009]维护序列_线段树

    BZOJ_1798_[AHOI2009]维护序列_线段树 题意:老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: ( ...

  9. BZOJ_3307_雨天的尾巴_线段树合并+树上差分

    BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...

随机推荐

  1. x&(x-1)

    x&(x-1)可以用来求出x是否为2幂次方数:当&的结果为0时,x原值是2幂次方数,否则就不是2幂次方数: x=x&(x-1)即把x从低位开始的第一个1改成0.如1000,把1 ...

  2. Ubuntu下定时任务和自启动任务的部署

    1.定时任务的部署,最简单的方法是执行 crontab -e 然后在下面加上世间周期配置和要执行的命令,一般情况下,可以把要执行的任务用bash脚本封装一下,格式如下所示: minute   hour ...

  3. Flask第三方工具组件介绍

    flask-wtf组件flask-login组件flask-session组件flask-sqlalchemy组件flask-script组件flask-cache组件flask-assets组件fl ...

  4. php判断图片是否存在的几种方法

    在我们日常的开发中,经常需要用到判断图片是否存在,存在则显示,不存在则显示默认图片,那么我们用到的判断有哪些呢?今天我们就来看下几个常用的方法: 1.getimagesize()函数 getimage ...

  5. Flex 右键菜单控制

    //设置监控右键菜单项 private function setUserMenuItem():void{ var contextMenu:ContextMenu = new ContextMenu() ...

  6. Socket 异步通信

    最近在写数据通信的时候用到的东西!希望对大家有帮助 /// <summary> /// 获取或设置服务器IP地址 /// </summary> public string se ...

  7. CSS学习笔记1:基础知识

    CSS规则由两部分组成,选择器和声明     选择器:标签,告诉浏览器哪些标签需要用到这个样式     声明:样式的内容,由一或多对属性:值以:隔开组成,由{}包围,需要多个选择器时以逗号隔开     ...

  8. 40多行python代码开发一个区块链。

    40多行python代码开发一个区块链?可信吗?我们将通过Python 2动手开发实现一个迷你区块链来帮你真正理解区块链技术的核心原理.python开发区块链的源代码保存在Github. 尽管有人认为 ...

  9. spring事务机制

    一.Java动态代理 1.定义 Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 默认情况下会采用JDK的动态代理实现AOP . 2. ...

  10. webpack bug及解决方案

    1.webpack打包后z-index失效 解决方案:z-index设置成行内样式,例如:root.style.cssText = 'z-index:100000 !important;';