「CF 1180C」 Valeriy and Deque

题目大意

给定一个双端队列,然后给定一个 \(operationn\),每一个 \(operation\) 可以实现以下步骤:

取出队列的前两个元素,分别是 \(A\),\(B\)。
如果 \(A>B\),那么 \(A\) 加入到这个队列的 \(front\),\(B\) 加入到 \(back\),否则 \(A\) 加入 \(back\),B加入 \(front\)。,然后给你 \(q\) 个询问,每一个询问是问你从原始数组开始执行第 \(x\) 次 \(operation\) 时,\(A\) 和 \(B\) 分别是多少?

分析

首先想到用 \(deque\) 模拟,但肯定会超时。
注意到当最大数被操作到首位后就不会再移动,那剩下的数就会形成循环。
所以我们只需要用 \(deque\) 模拟直到首位是最大值,求出循环节就行了。可以证明最多模拟 \(n\) 次。

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
int n,m,_max;
int lst,x[M],y[M],b[M];
deque<int> G;
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1,x;i<=n;i++){
		scanf("%d",&x);
		_max=max(_max,x);
		G.push_back(x); 
	}
	int now=0;
	while(1){
		if(G.front()==_max) break;//判断首位是否最大值 
		int p=G.front();
		G.pop_front();
		int q=G.front();
		G.pop_front();//模拟 
		x[++now]=p;
		y[now]=q;
		if(p<q) swap(p,q);
		G.push_front(p);
		G.push_back(q);	
	}
	if(G.size()) G.pop_front();
	while(G.size()){//求循环节 
		b[++lst]=G.front();
		G.pop_front();
	}
	for(int i=1;i<=m;i++){
		long long o;
		scanf("%lld",&o);
		if(o<=now){
			printf("%d %d\n",x[o],y[o]);
			continue;
		}
		else{
			o-=now;
			printf("%d %d\n",_max,b[(o-1)%(n-1)+1]);
		}
	}
}
上一篇:微信小程序开发(3)事件绑定


下一篇:11、Java模式--装饰器模式