求最左边的人,与最右边的人。最关键的地方就在于高个会把低个挡住。
所以维持一个单调递减的单调队列。每个元素都要入队列,出队列就有如下考虑
for(i ->n)
(1)第i个元素比front大 ,说明队列中所有的人都会被挡住。清空队列
(2)第i个元素front小,那他可能挡住队列中的某些人,从rear->front,”弹出“比第i个人矮的,直到遇见比他高的人。
(3)队列为空
/*题意:
给定n长的数组(下标从1-n)(n个人的身高,身高各不相同
问:对于第i个人,他能看到的最左边的的人下标。(如果这个最矮的人被挡住了,
则这个值为0)
还有最右边的人下标,同理若被挡住了则这个值为0
输出n行,每个人左右2边的下标。*/
#include <stdio.h>
#include <stack>
#define MAX_N 50008
#define INF 0x3f3f3f3f
using namespace std;
int v[MAX_N];
int ans[MAX_N][2];
int que[MAX_N];
int main()
{
int t;
scanf("%d",&t);
int cnt=1;
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",v+i);
int front=0,rear=-1;
for(int i=1;i<=n;++i)
{
if(front>rear)
ans[i][0]=0;
else {
if(v[que[front]]<=v[i])
ans[i][0]=que[front],rear=front-1;
else
{
int u=0;
while(front<=rear&&v[que[rear]]<=v[i])
u=que[rear],--rear;
ans[i][0]=u;
}}
que[++rear]=i;
}
front=0,rear=-1;
for(int i=n;i>0;--i)
{
if(front>rear)
ans[i][1]=0;
else {
if(v[que[front]]<=v[i])
ans[i][1]=que[front],rear=front-1;
else
{
int u=0;
while(front<=rear&&v[que[rear]]<=v[i])
u=que[rear],--rear;
ans[i][1]=u;
}}
que[++rear]=i;
}
printf("Case %d:\n",cnt++);
for(int i=1;i<=n;++i)
printf("%d %d\n",ans[i][0],ans[i][1]);
}
return 0;
}