• 【BZOJ1826】【洛谷P4404】缓存交换【贪心】【堆】


    题目大意:

    题目链接:
    BZOJ:https://www.lydsy.com/JudgeOnline/problem.php?id=1826
    洛谷:https://www.luogu.org/problemnew/show/P4404

    在计算机中,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缺失次数。


    思路:

    首先,当Cache满了之后,选择已有单元中下一次出现位置最后的删除是最优秀的。因为删除的位置越后,中间可以避免其他的缺失个数就越多,相对的缺失次数就会越少。
    维护next[x]next[x]表示下一个和元素a[x]a[x]相同的元素位置。这个是可以O(n)O(n)求出来的。
    然后我们要维护多个二元组(x,i)(x,i),其中ii表示选择第ii个位置的元素,xx表示next[i]next[i]。我们要在选择的不超过mm个二元组中选择xx尽量大的删除。所以可以用优先队列来维护。
    注意到若两个元素x,yx,y相同,设xx的位置在yy后面(xx入队时间比yy晚),那么必然有next[x]>next[y]next[x]>next[y]。所以其实可以不用删除前面的yy,因为xx必然可以覆盖掉yy,在yy的前面出队。
    时间复杂度O(nlogn)O(nlog n)


    代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define mp make_pair
    using namespace std;
    
    const int N=100010;
    int n,m,tot,ans,sum,a[N],b[N],last[N],next[N];
    priority_queue<pair<int,int> > q;
    bool inque[N];
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		b[i]=a[i];
    	}
    	sort(b+1,b+1+n);
    	tot=unique(b+1,b+1+n)-b-1;
    	for (int i=1;i<=n;i++)
    		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    	memset(last,0x3f3f3f3f,sizeof(last));
    	for (int i=n;i>=1;i--)
    	{
    		next[i]=last[a[i]];
    		last[a[i]]=i;
    	}
    	for (int i=1;i<=n;i++)
    	{
    		if (ans<m && !inque[a[i]])
    		{
    			ans++;
    			inque[a[i]]=1;
    		}
    		else if (ans>=m && !inque[a[i]])
    		{
    			ans++;
    			inque[a[i]]=1;
    			inque[q.top().second]=0;
    			q.pop();
    		}
    		q.push(mp(next[i],a[i]));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    5.11-上位机重新编程
    3.30-计算机系统互联方案
    3.25-两个操作者的通信模式
    3.23-重新定义操作者框架
    go 修改数组中对象的值不生效的解决方法
    go orm QueryTable Filter 不生效解决方法
    Beego orm.Install() 插入 [单条记录] 或 [一批记录],及出现异常 Handler crashed with error <Ormer> table: `.` not found, make sure it was registered with `RegisterModel()`
    go json 序列号、反序列号和数据类型转换
    go json 转换忽略字段、控制字段可有可无
    Flutter 使用 flutter_inappbrowser 加载 H5 及与 js 交互,Methods marked with @UiThread must be executed on the main thread . Current thread: JavaBridge
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998101.html
Copyright © 2020-2023  润新知