LRU Algorithm Gym

LRU Algorithm

[Time Limit: 1000 msquad Memory Limit: 524288 kB ]

题意

给出 (n) 个数字和 (m) 次查询。
每次询问中,给出 (L) 表示 (LRU) 中缓存器的大小,再给出 (L) 个数字,问对 (n) 个数字做大小为 (L)(LRU) 过程中,会不会有某一时刻,缓存器中的数字序列和给出的 (L) 个数字一致。

思路

首先对于 (LRU) 算法,当缓存器大小为 (L)时,以某个位置 (pos) 结束的缓存器中的元素,本质上就是从 (pos) 往前的 (L) 个第一次出现的不同的数字。所以每次查询我们只要想办法找出以每个位置结束,往前 (L) 个不同的数字是什么,然后判断和所查询的序列是否一致,就可以知道是 (Yes) 或者是 (No) 了。

首先发现 (n=5000),那么可以 (n^2) 暴力预处理出 (has[i][j]),表示从 (i) 开始,往前 (j) 个不同的数字所构成的 (hash) 值,然后只要判断给出的 (L) 个数字的 (hash) 值是否满足条件就可以了。注意判断一下不满 (L) 个元素的情况,那就还要求找到的 (pos) 位置以前只存在给出的数字。

/*************************************************************** 
	> File Name		: L.cpp
	> Author		: Jiaaaaaaaqi
	> Created Time	: Tue 12 Nov 2019 04:58:09 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e3 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int aa[maxn];
int a[maxn], b[maxn];
int vis[maxn], pre[maxn];
ull has[maxn][maxn], seed = 233;

int main() {
	// freopen("in", "r", stdin);
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &m);
		for(int i=1; i<=n; i++)	scanf("%d", &aa[i]);
		int len1 = 0, len2 = 0;
		for(int i=1; i<=n; i++) {
			if(n==0 || aa[i]!=a[len1])	a[++len1] = aa[i];
		}
		for(int i=1; i<=n; i++)	vis[i] = pre[i] = 0;
		for(int i=1; i<=n; i++) {
			pre[i] = pre[i-1];
			if(vis[a[i]] == 0)	pre[i]++;
			vis[a[i]]++;
		}
		for(int i=n; i>=1; i--) {
			for(int j=1; j<=n; j++)	vis[j] = 0;
			int cnt = 0;has[i][0] = 0;
			for(int j=i; j>=1; j--) {
				if(vis[a[j]] == 0) {
					cnt++;
					has[i][cnt] = has[i][cnt-1] * seed + a[j];
				}
				vis[a[j]]++;
			}
		}
		while(m--) {
			scanf("%d", &len2);
			for(int i=1; i<=len2; i++)	scanf("%d", &b[i]);
			bool flag = 0;
			while(len2 && b[len2] == 0)	len2--, flag = 1;
			if(len2 == 0) {
				printf("Yes
");
				continue;
			}
			ull ans = 0;for(int i=1; i<=len2; i++)	ans = ans*seed+b[i];
			int pos = 0;
			for(int i=1; i<=len1; i++) {
				if(has[i][len2] == ans) {
					pos = i;
					break;
				}
			}
			if(pos && (!flag || (flag && pre[pos]==len2)))	printf("Yes
");
			else	printf("No
");
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11971234.html