求最左邊的人,與最右邊的人。最關鍵的地方就在於高個會把低個擋住。
所以維持一個單調遞減的單調隊列。每個元素都要入隊列,出隊列就有如下考慮
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;
}