1. 程式人生 > 其它 >Passing the Message

Passing the Message

Passing the Message-HDU3410

題目連結: [](Problem - 3410 (hdu.edu.cn))

小難啊這題....

$2^8$

題目大意:

輸出每一個位置的人向左/右看,看到的比他矮的最高的人的下標。(每個同學的身高不一樣)如果有人比他高那就看不到那個比他高的人後面了(視野會被擋住)

思路:

只要解決向右看,向左看就迎刃而解了,只是方向不一樣。

對於每一個位置i,只記錄[i+1,n]中的最大值是不夠的,因為很有可能最大值所在位置和i之間有符合比i矮的最大的這一條件位置。

需要維護一個棧頂到棧底遞增的單調棧來記錄i後面的情況。舉個例子,如果i位後是4 3 5,這個3是多餘的,因為i位無非兩種情況:1. i<=4 那麼i根本看不到3;2. i>4 那麼i雖然可以看到3,但是找最大值是輪不到這個3的(有4,5在)

例子:

因為向右邊看要得出準確答案需要右邊的區間提前處理完畢,所以向右邊看就是從後往前遍歷,反之則從前往後遍歷。

總的來說,要維護一個範圍為[i+1,n]的單調棧(棧頂到棧低單調遞增),供i往後面找符合條件的值,並且在找的過程中,通過彈棧保持單調性。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define drep(i,a,b) for(int i=b;i>=a;i--)
using namespace std;
const int N = 5*1e5+50;
int T,n,cas;
struct kid{
	int h,idx;
}a[N];
int ansl[N],ansr[N];

void solve(){
	stack<kid>st;
	drep(i,1,n){
		while(st.size() && st.top().h<=a[i].h){
			if(st.top().h != a[i].h)ansr[i]=st.top().idx;
			st.pop();
		}st.push(a[i]);
	}
	stack<kid>sk;
	rep(i,1,n){
		while(sk.size() && sk.top().h<=a[i].h){
			if(sk.top().h != a[i].h)ansl[i]=sk.top().idx;
			sk.pop();
		}sk.push(a[i]);
	}
	printf("Case %d:\n",++cas);
	rep(i,1,n)printf("%d %d\n",ansl[i],ansr[i]);
	
	
}

int main(){
	scanf("%d",&T);
	while(T--){
		memset(ansr,0,sizeof ansr);
		memset(ansl,0,sizeof ansl);
		scanf("%d",&n);
		a[n+1].h=a[n+1].idx=0;
		rep(i,1,n){
			scanf("%d",&a[i].h);
			a[i].idx=i;
		}
		solve();
	}
}