1. 程式人生 > 其它 >「CF 1180C」 Valeriy and Deque

「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]);
		}
	}
}