LRU(模拟缓存)

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

It costs a long time for CPUs to access data from memory, so most of CPUs have caches where requests for data can be served faster. To be cost-effective and to enable efficient use of data, caches must be relatively small. Therefore, we must use some policies to choose some data wisely and storage them in the cache. We divide the memory into many blocks which have the same size and index them from 1 to 109109, and every block has an unique index. A cache will have a capacity for KK blocks, which means it can storage at most KK blocks simultaneously. A cache hit occurs when the requested block is available in the cache, or we say a cache miss occurs. Now we introduce a LRU (Least Recently Used) placement policy on a fully associative cache.

  1. If the requested block is available in the cache, a cache hit occurs.
  2. If not, CPU can only access the block from the memory and write the block into the cache. If cache is not full, append the block into the cache.
  3. If the cache is full, cache is full, the block which haven't been visited for the longest time in the cache will be replaced by the new block.

An example for cache with capacity of 33 blocks is shown below.

The 8th8th, 4th4th and 3rd3rd are in the cache when the 6th6th block is requested, so a cache miss occurs. At that time, the cache is full, and we must decide the block to be replaced. The most recent request of 8th8th block is the 13th13th request, the most recent request of 4th4th block is the 14th14th request and the most recent request of 3rd3rd block is the 11th11th request. The 3rd3rd block will be replaced by the 6th6th block because the 3rd3rd block hasn't been visited for longest time.

Now the sequence of requested blocks and the capacity of the cache are given, please determine the minimum capacity for the cache in order to ensure at least K requests to hit the cache.

Input

The first line contains two integers NN and K(1≤K≤N≤105)K(1≤K≤N≤105), denoting the length of sequence and the number of requests required to hit the cache. The second line contains NN integers and the ithith integers ai(1≤ai≤109)ai(1≤ai≤109) denoting the index of the block requested by the ithith request.

Output

The output contains only one line. If it is possible to ensure at least KK requests to hit the cache, then output a single integer denoting the smallest capacity in blocks, otherwise output "cbddl"(without quotes).

Examples

input

Copy

15 6
3 4 2 6 4 3 7 4 3 6 3 4 8 4 6

output

Copy

3

input

Copy

15 5
3 4 2 6 4 3 7 4 3 6 3 4 8 4 6

output

Copy

3

input

Copy

15 10
3 4 2 6 4 3 7 4 3 6 3 4 8 4 6

output

Copy

cbddl

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define endl '\n'

using namespace std;
typedef long long ll;
const int N = 1e5 + 10; 
unordered_map<int, int> ump, w;// 对于大数的桶直接用它 
int n, k;
int a[N];
struct node
{
	int value;
	int time;
	friend bool operator < (node x, node y)// 对优先队列的自定义排序,我只会在结构体中排,其他不会,背了就完事 
	{
		return x.time > y.time;// time指的是代表的是优先级,越小越要被替换,还有这个优先队列的排序要和sort里的规则相反,不知道为什么,到时候再学 
	}
};



int check(int capacity)
{
	w.clear();
	set<int> s;
	priority_queue<node> heap;// log(n)的复杂度 
	int ans = 0;
	int time = 0;
	node x;
	for (int i = 1; i <= n; ++i)
	{
		if (s.count(a[i]) == 0)// set里面没有找到,那就要进行插入操作 
		{
			if (s.size() < capacity)
			{
				time++;
				s.insert(a[i]);
				x.time = time, x.value = a[i];
				heap.push(x);
			}
			else if (s.size() == capacity)
			{
				node y = heap.top();
				while (w[y.value])// 这一步很重要,利用桶的思想进行删除,典型的空间换时间 
				{
					w[y.value]--;
					heap.pop();
					y = heap.top();
				}
				heap.pop();
				s.erase(y.value);
				time++;
				s.insert(a[i]);
				x.time = time, x.value = a[i];
				heap.push(x);
			}
		}
		else if (s.count(a[i]) == 1)
		{
			time++;
			w[a[i]]++;// 找到了直接上桶,为的是要防止插入的时候影响其他值 
			x.time = time, x.value = a[i];
			heap.push(x);
			ans++;
		}
	}
	if (ans >= k)// 说明符合条件的点比k多 
		return 1;
	else 
		return 0;	
}

int main()
{
	IOS; cin.tie(0), cout.tie(0);
	cin >> n >> k;
	int sum = 0;
	int different = 0;// 代表到底有几个数是不同的,确定二分区间 
	for (int i = 1; i <= n; ++i)
	{
		int num;
		cin >> num;
		if (ump[num] == 0)
			different++;
		if (ump[num] != 0)
			sum++;
		ump[num]++;
		a[i] = num;
	} 
	if (sum < k)// 假设容量最大化都无法容纳完,那么肯定是不行的 
		cout << "cbddl" << endl;
	else
	{
		int l = 1, r = different, mid;
		while (l <= r)
		{
			mid = (l + r) / 2;
			if (check(mid))
				r = mid - 1;
			else
				l = mid + 1;	
		}
		cout << l << endl;
	}	
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值