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

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

#include
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;
}

你可能感兴趣的:(比赛题解)