• luoguP4404缓存交换


    https://www.luogu.org/problem/P4404

    题意

    你有一个大小为n的缓存区,有个长度为m的查询序列。

    每次查询的时候需要把查询值放入缓存,若缓存已满,则先删除任一位置再将其放入,若缓存内已有当前值,则无需再次放入

    求放入缓存这个操作的最少执行次数

    n,m≤1e5

    序列中的数<=1,000,000,000

    分析

    很明显的贪心, 但要想想贪心的策略

    其实这题做的很玄(感觉我每次做题都很玄,因为是听完luogu讲师讲完之后做的题目,思路什么的都有提示...

    这道题首先要做的就是把前m个不同的数放到缓存里面,然后依次加数,删数...也就是一个模拟。

    但怎么删数呢?这里给出的策略是删除缓存中一个数x: 在缓存外,x对应的第一个与它相等的数y 的位置最靠后。

    原因:(我只知道这样做是对的,但不知道怎么想到的...毕竟我只画了几个例子,思路老师说的)

    这样子做,可以使删除操作对放入缓存次数的影响最小,即 使放入缓存的操作数增加的最小,如果我们不这做,那么 y 之前必定有数z,经历了先删除又放入,而先删x的话,至少不会使放入缓存的操作更多....吧(我其实也不是hin懂,看看实现就行了

    实现:预处理一下y(即代码中的next),用堆存这个玩意,注意离散化,注意模拟的过程就好了

    实现

    #include<cstdio>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    #define MAX 100000+9
    
    int n,m,ans, tag = 1;
    struct node{
    	int a,n,k;
    }a[MAX];
    bool cmp1(node x, node xxx) { return x.a < xxx.a;}
    bool cmp2(node x, node xxx) { return x.n < xxx.n;}
    
    int last[MAX], next[MAX], vis[MAX];
    struct node2{
    	int num, next;
    	bool operator < (const node2& xxx) const {
    		return next < xxx.next ;
    	}
    };
    
    priority_queue<node2> q;
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for(int i = 1; i <= n; i++) scanf("%d",&a[i].a ), a[i].n = i;
    	sort(a+1, a+1+n, cmp1);
    	int tot = 0;
    	for(int i = 1; i <= n; i++) {
    		a[i].k = ++tot;
    		while(a[i+1].a == a[i].a ) a[++i].k = tot;
    	}
    	sort(a+1, a+1+n, cmp2);
    //	for(int i = 1; i <= n; i++) printf("%d ",a[i].k );
    //	printf("
    ");
    	//注意,若满的缓存区里有一元素x,并且查询序列中没有了x,那么x一定是要先删的,所以设为INF 
    	memset(last , 0x3f , sizeof(last));
    	for(int i = n; i >= 1; i--) {
    		next[i] = last[a[i].k ];
    		last[a[i].k ] = i;
    	}
    //	for(int i = 1; i <= n; i++) printf("%d ",next[i] );
    //	printf("
    ");
    	for(int i = 1; i <= n; i++) {
    		if(ans == m) {
    			tag = 2;
    		}
    		if(tag == 1 && vis[a[i].k] == 0) {//没放满m ,且a[i].k不在队中 
    			ans++;
    			vis[a[i].k ] = 1;
    		}
    		if(tag == 2 && vis[a[i].k] == 0) {//放满的m,且a[i].k不在队中 
    			ans++;
    			vis[a[i].k ] = 1;
    			vis[q.top().num] = 0;
    			q.pop();
    		}
    		node2 tmp;
    		tmp.num = a[i].k , tmp.next = next[i];
    		q.push(tmp); 
    	}
    	printf("%d",ans);
    	return 0;
    } 
    /*
    6 2
    1 222 3333 1 222 3333
    */
    
  • 相关阅读:
    UVA 1386
    疯狂Android演讲2 环境配置
    七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
    【iOS发展-44】通过案例谈iOS重构:合并、格式化输出、宏观变量、使用数组来存储数据字典,而且使用plist最终的知识
    jQuery选择
    一个月操作总结
    C++易vector
    oracle rac 在完成安装错误。
    NginX issues HTTP 499 error after 60 seconds despite config. (PHP and AWS)
    解决Eclipse中文乱码的方法
  • 原文地址:https://www.cnblogs.com/tyner/p/11271560.html
Copyright © 2020-2023  润新知