[2019CCPC哈尔滨] L LRU Algorithm 模拟

本文介绍了一种处理序列插入和删除操作的算法,通过维护元素出现的次序,判断给定序列是否能在特定条件下出现。算法包括处理元素插入、删除、判断序列合法性以及通过倒序贪心策略检查序列匹配。

给一个n≤5e3n\leq5e3n5e3的序列,这个序列从左往右表示每次都往里面插入一个元素,如果这个元素不在里面,那么会插入在头部,否则就删除掉在原来的位置并且重新插入到头部。然后如果插入的元素超过容量,那么就会将尾部的弹出。
并且给出q≤2e3q\leq2e3q2e3次询问。对于每次询问,给定一个容量,然后和一个序列,现在要判断这个序列是否在整个插入的过程中出现过,忽略后缀000
显然对于一个元素出现超过一次以及000后面出现元素这样不合法的序列是一定不会出现的,否则记录下对于每个元素出现的次序ordiord_{i}ordi
然后每次询问从原序列中倒序贪心。如果这个元素没有标记或者中间的缺失,那么就从下一段开始,直到遍历完或者发现可以匹配为止。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=5e3+7;
int n,q;
int a[N]; 
int vis[N];
bool ok=1;
int sz,cnt,zero;
void reset() {
	ok=1;cnt=0;zero=0;
	for(int i=1;i<=n;i++)  vis[i]=0;
}
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d",&n,&q);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		while(q--) {
			reset(); 
			scanf("%d",&sz);
			for(int x,i=1;i<=sz;i++) {
				scanf("%d",&x);
				if(!x) zero=1;
				else  ++cnt;
				if(zero) {
					if(!x) continue;
					else ok=0;
				} 
				if(vis[x]) ok=0;
				vis[x]=i;
			}
			if(!ok) {
				puts("No");
				continue;
			}
			int now=0,flag=0;
			for(int i=n;i>=1;i--) {
				if(!vis[a[i]]||vis[a[i]]>now+1)
					now=0;
				if(vis[a[i]]==now+1) now++;
				if(now==cnt) { flag=1; break; }
			}
			if(flag) puts("Yes");
			else puts("No");
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值