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


發佈了94 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章