hdu 3410 单调栈

http://acm.hdu.edu.cn/showproblem.php?pid=3410

Passing the Message

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 827    Accepted Submission(s): 546

Problem Description

What
a sunny day! Let’s go picnic and have barbecue! Today, all kids in “Sun
Flower” kindergarten are prepared to have an excursion. Before kicking
off, teacher Liu tells them to stand in a row. Teacher Liu has an
important message to announce, but she doesn’t want to tell them
directly. She just wants the message to spread among the kids by one
telling another. As you know, kids may not retell the message exactly
the same as what they was told, so teacher Liu wants to see how many
versions of message will come out at last. With the result, she can
evaluate the communication skills of those kids.
Because all kids have different height, Teacher Liu set some message passing rules as below:

1.She tells the message to the tallest kid.

2.Every kid who gets the message must retell the message to his “left messenger” and “right messenger”.

3.A kid’s “left messenger” is the kid’s tallest “left follower”.

4.A
kid’s “left follower” is another kid who is on his left, shorter than
him, and can be seen by him. Of course, a kid may have more than one
“left follower”.

5.When a kid looks left, he can only see as far as the nearest kid who is taller than him.

The
definition of “right messenger” is similar to the definition of “left
messenger” except all words “left” should be replaced by words “right”.

For
example, suppose the height of all kids in the row is 4, 1, 6, 3, 5, 2
(in left to right order). In this situation , teacher Liu tells the
message to the 3rd kid, then the 3rd kid passes the message to the 1st
kid who is his “left messenger” and the 5th kid who is his “right
messenger”, and then the 1st kid tells the 2nd kid as well as the 5th
kid tells the 4th kid and the 6th kid.
Your task is just to figure out the message passing route.

Input

The first line contains an integer T indicating the number of test cases, and then T test cases follows.
Each
test case consists of two lines. The first line is an integer N (0< N
<= 50000) which represents the number of kids. The second line lists
the height of all kids, in left to right order. It is guaranteed that
every kid’s height is unique and less than 2^31 – 1 .

Output

For
each test case, print “Case t:” at first ( t is the case No. starting
from 1 ). Then print N lines. The ith line contains two integers which
indicate the position of the ith (i starts form 1 ) kid’s “left
messenger” and “right messenger”. If a kid has no “left messenger” or
“right messenger”, print ‘0’ instead. (The position of the leftmost kid
is 1, and the position of the rightmost kid is N)

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

Source

2010 National Programming Invitational Contest Host by ZSTU

要找的就是每个元素左右两侧能看见的(如果被更高的挡住就表示看不见)比这个人低的所有人里最高的那个,没有的话输出0;

显然具有单调性,当比栈顶还低/空栈时表示没符合条件的人,输出0并入栈;

当高于栈顶时,由于是一个单调递减栈,一直出栈找到符合条件的最高者记下id即可,记得把这个人最后入栈;

由于i=k时出栈的都是比a[k]矮的人,后面出现a[j]<a[k]的情况显然他看不见pop掉的人,如果a[j]>a[k]则选a[k]显然优于选pop掉的人,所以可以pop掉;

 1 #include <iostream>
 2 #include<algorithm>
 3 #include<stack>
 4 #include<cstdio>
 5 #include<cstring>
 6 using namespace std;
 7 typedef long long LL;
 8 const int MAX = 50005;
 9 int a[MAX], l[MAX], r[MAX];
10 int main()
11 {
12     int N, i, j, k, t;
13     scanf("%d", &t);
14     for (int cas = 1;cas <= t;++cas)
15     {
16         stack<int>S;
17         //memset(l, 0, sizeof(l));
18         //memset(r, 0, sizeof(r));
19         scanf("%d", &N);
20         for (i = 1;i <= N;++i) scanf("%d", &a[i]);
21         for (i = 1;i <= N;++i) {
22             if (S.empty() || a[i]<a[S.top()]) {
23                 l[i] = 0;
24                 S.push(i);
25             }
26             else {
27                 while (!S.empty()&&a[S.top()]<a[i]) {
28                     l[i] = S.top();
29                     S.pop();
30                 }
31                 S.push(i);
32             }
33         }while (!S.empty())S.pop();
34         for (i = N;i >= 1;--i) {
35             if (S.empty() || a[i]<a[S.top()]) {
36                 r[i] = 0;
37                 S.push(i);
38             }
39             else {
40                 while (!S.empty() && a[S.top()]<a[i]) {
41                     r[i] = S.top();
42                     S.pop();
43                 }
44                 S.push(i);
45             }
46         }
47         printf("Case %d:\n", cas);
48         for (i = 1;i <= N;++i) printf("%d %d\n", l[i], r[i]);
49     }
50     return 0;
51 }
时间: 2024-08-04 15:31:48

hdu 3410 单调栈的相关文章

hdu 1506 单调栈问题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题目的意思其实就是要找到一个尽可能大的矩形来完全覆盖这个矩形下的所有柱子,只能覆盖柱子,不能留空. 我们求得的面积其实就是Max{s=(right[i] - left[i] + 1)*height[i];(i>=1&&i<=n)} 每一个柱子都要尽可能向左向右延伸,使得获得最大的面积. 此时我就要用到单调栈 单调栈就是栈内元素单调递增或者单调递减的栈,单调栈只能在栈顶操作.

HDU 5033---Building(单调栈)

题目链接 Problem Description Once upon a time Matt went to a small town. The town was so small and narrow that he can regard the town as a pivot. There were some skyscrapers in the town, each located at position xi with its height hi. All skyscrapers loc

hdu 5875(单调栈)

Function Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1866    Accepted Submission(s): 674 Problem Description The shorter, the simpler. With this problem, you should be convinced of this tr

hdu 5033 单调栈 ****

看出来是单调栈维护斜率,但是不会写,2333,原来是和询问放在一起的 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <cmath> 7 typedef __int64 ll; 8 using namespace std; 9 10 const doub

HDU 5033 (单调栈维护凸包) Building

题意: 一个人在x轴上,他的左右两侧都有高楼,给出楼的横坐标Xi和高度Hi还有人的位置pos,求人所能看到的天空的最大角度. 分析: 将建筑物和人的位置从左到右排序,对于每个位置利用栈求一次人左边建筑物的凸包,找到一个最小的角度,然后对称一下,再找一个右边的建筑物的最小角度,两个角度加起来就是答案. 将人左边的建筑物从左到右扫描,下面两种情况会出栈: 栈顶元素楼高小于等于当前扫描到的楼高,因此这是一个单调的栈 栈顶两个楼顶所在直线的斜率 小于 栈顶的楼顶和当前楼顶所在直线的斜率(这里的斜率指的是

HDU 4923 Room and Moor (多校第六场C题) 单调栈

Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that: Input The inp

HDU 2870 Largest Submatrix (单调栈)

http://acm.hdu.edu.cn/showproblem.php?pid=2870 Largest Submatrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1569    Accepted Submission(s): 748 Problem Description Now here is a matrix wit

hdu - 5033 - Building(单调栈)

题意:N 幢楼排成一列(1<=N<=10^5),各楼有横坐标 xi(1<=xi<=10^7) 以及高度 hi(1<=hi<=10^7),在各楼之间的Q个位置(1<=Q<=10^5),问这些位置可以仰望天空的夹角是多少度. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033 -->>将楼和人的位置一起按 x 排序.. 从左往右扫,单调栈维护斜率小的.. 从右往左扫,单调栈维护斜率大的.. #inc

HDU 3410 &amp;&amp; POJ 3776 Passing the Message 单调队列

题意: 给定n长的数组(下标从1-n)(n个人的身高,身高各不相同 问:对于第i个人,他能看到的左边最矮的人下标.(如果这个最矮的人被挡住了,则这个值为0) 还有右边最高的人下标,同理若被挡住了则这个值为0 输出n行,每个人左右2边的下标. 单调队列,对于 front - rear 的队列(注意出队都是在rear,入队也是在rear) 当加入元素x,若这队列是单调递增的,显然q.front() <= x , 反之若>x ,则把队首元素弹掉,这样就能保持单调性. 若弹掉了队首元素,在此题中就相当