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在)

例子:

Passing the Message

因为向右边看要得出准确答案需要右边的区间提前处理完毕,所以向右边看就是从后往前遍历,反之则从前往后遍历。

总的来说,要维护一个范围为[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();
	}
}

Passing the Message

上一篇:C#窗体嵌套


下一篇:C# http get与post请求方法