题目大意
给定一个双端队列,然后给定一个 \(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]);
}
}
}