hdu 3410 单调栈

Description

现在有n个人站成一行,告诉你每个人的身高。
现在每个人都要找到在他左边,比他矮的人中最高的人的位置。
同时也要找到,在他右边比他矮的人中最高的人的位置。
注意由于他们是站成一行的,所以他们不能越过比他们高的人去看后面的人。也就是说,他只能看到他本人和他的左边(或右边)第一个比他高的人之间的那些人。
请输出每个人左边比他矮的人中最高的人的位置,以及每个人的右边比他矮的人中最高的人的位置(没有的话输出0,位置从1开始)

Input

第一行输入一个整数T,表示有T组数据。

每一组数据包含两行,第一行输入一个整数n(0 < n <= 50000),表示有n个人。第二行有n个整数,表示所有人的身高。

数据保证每个人的身高都是不同的,而且身高小于2^31。

Output

对于每组数据,输出“Case t:” ( t 表示是第几组数据的答案, t从1开始,双引号不算 )。

然后输出n行,第i行包含两个整数,表示第i个人的左边符合条件的人的位置和右边符合条件的人的位置。如果没有输出0,有就输出位置(位置从1开始)

Sample Input

2
5
5 2 4 3 1
5
2 1 4 3 5

Sample Output

Case 1:
0 3
0 0
2 4
0 5
0 0
Case 2:
0 2
0 0
1 4
0 0

3 0

思路:维护一个单减栈,如果当前要进栈的元素小于栈顶则直接进栈说明当前它最小则不能延伸,赋值为0,如果当前进栈的元素大于栈顶就一直POP直到可以入栈,就找到了左右比他矮的中最大的;

#include<stdio.h> #include<stack> #include<string.h> #define N 50010 using namespace std; int a[N]; int l[N]; int r[N]; int main() {     int t,i;       int k=1;      scanf("%d",&t);       while(t--)       {  memset(l,0,sizeof(l));          memset(r,0,sizeof(r));          stack<int>st,q;     while(!st.empty())      st.pop();      int n;     scanf("%d",&n);            for(i=1;i<=n;i++)  {      scanf("%d",&a[i]);              if(st.empty())              { l[i]=0;                st.push(i); } else { if(a[st.top()]<a[i]){ while(st.empty()==0&&a[st.top()]<a[i]) {        l[i]=st.top();          st.pop(); }  st.push(i);     }    else      {      l[i]=0;              st.push(i);  }  }     }     //while(!st.empty())     //st.pop();     for(i=n;i>=1;i--)     {   if(q.empty())          { r[i]=0;            q.push(i);  }     else  {      if(a[q.top()]<a[i])         {   while(q.empty()==0&&a[q.top()]<a[i])             {   r[i]=q.top();                 q.pop(); } q.push(i); } else { r[i]=0;   q.push(i); }    } } printf("Case %d:\n",k++); for(i=1;i<=n;i++) printf("%d %d\n",l[i],r[i]);  }  return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marcus-Bao

万水千山总是情,只给五角行不行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值