思路:求每个人的左使者就是从左到右把每个人加入到单调队列中去,加入时最后一个出队的就是那个最大的小于这个数的数
求右信使同理
由于本题的单调队列队头不需要出队,所以其实是一个单调栈
/* 每个人只要找到左(右)边的比它小的最大的数即可,用单调队列模拟即可 */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define maxn 50005 #define ll long long using namespace std; int a[maxn],ans[maxn][2],n; int main(){ int t; scanf("%d",&t); for(int tt=1;tt<=t;tt++){ printf("Case %d: ",tt); memset(ans,0,sizeof ans); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int last,l=0,r=0,q[maxn]; q[0]=0; for(int i=1;i<=n;i++){ last=0; while(l<r && a[i]>a[q[r-1]]) r--,last=q[r]; q[r++]=i;ans[i][0]=last?last:0; } q[0]=0;l=0,r=0; for(int i=n;i>=1;i--){ last=0; while(l<r && a[i]>a[q[r-1]]) r--,last=q[r]; q[r++]=i;ans[i][1]=last?last:0; } for(int i=1;i<=n;i++) printf("%d %d ",ans[i][0],ans[i][1]); } return 0; }