hdu-3410 Passing the Message[单调队列]

求最左边的人,与最右边的人。最关键的地方就在于高个会把低个挡住。

所以维持一个单调递减的单调队列。每个元素都要入队列,出队列就有如下考虑

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;
}


你可能感兴趣的:(单调队列)