窃取任务
Time Limit: 1000 ms Memory Limit: 64 MB
Description
战争期间,双方互打信息战,我军准备去敌方一条战斗主线上的信息塔窃取他们的信息。敌方的信息塔排成了一条线,每个信息塔都会同时向两侧(两端的塔只向一侧)严格比自己高的最近的信息塔传送信息。现在时间紧迫,我们只能去其中一个信息塔,为了最高效的窃取敌人的信息,我们必须选择其中信息接收量最大的塔。现在请你去执行这个窃取任务。
Input
第1行,一个整数N(1<=N<=50000),表示这条线上有多少个信息塔。
第2行,N个整数h1到hn,其中hi(1<=hi<=2000000)表示第i个塔的高度。
第2行,N个整数h1到hn,其中hi(1<=hi<=2000000)表示第i个塔的高度。
Output
仅1行,一个整数i表示信息接收量最大的塔的编号,如果有多个输出编号最小的。
Sample Input
Original | Transformed |
4 5 2 6 7
Sample Output
Original | Transformed |
3
Source
ZGF
————————————————————开森的分割线————————————————————
思路:本题AC得神清气爽!咳咳。。。。。。首先我们在POJ Largest Rectangle in a Histogram最大矩形直方图这道题当中艰难地学会了单调栈。这一题刚好拿来练手。首先我们要把问题简单化。双向发射信息有些难以理解。我们假设所有信号塔只能够向右发射信息。这时候我们看到,一个塔,只要右边没遇见比它高的塔,就必须一直发射信息直到找到了比它高的塔。每个塔都是这样。一旦遇到了比当前塔高的某个塔T,就需要回过头计算从当前塔直到第一个比T要高的,这之间所有塔都必须向T发射信息。然后,这些塔计算完毕,对了,出栈!这就是维护一个单调递减的栈。
准确地说,维护一个不增的栈。完成之后,再从右到左考虑,同理。
代码如下:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int a[50010], b[50010];//b[]数组保存了每个塔得到的信息量
int sta[50010];
int main(){
int n, top, pos, height;
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", a+i);
memset(b, 0, sizeof(b));
//首先维护一个单调递减的栈,只看向右发射信息的情况
top = -1; sta[++top] = a[0];
for(int i = 1; i < n; i++){
pos = i;//记录此塔的位置,以备出栈
height = a[i];
while(sta[top] < height && top != -1){//认真思考,为什么不取等于号。
top--;//一旦打破单调性,出栈
b[pos]++;//出去一个,T塔信息量+1
}
sta[++top] = height;//单调地入栈
}
//接着反过来维护一个单调递减的栈,只看向左发射信息的情况,复制之后稍微修改即可。
top = -1; sta[++top] = a[n-1];
for(int i = n-2; i >= 0; i--){
pos = i;
height = a[i];
while(sta[top] < height && top != -1){
top--;
b[pos]++;
}
sta[++top] = height;
}
int maxi = -1, ans;
for(int i = 0; i < n; i++)
if(b[i] > maxi){
maxi = b[i];
ans = i+1;
}
printf("%d\n", ans);
return 0;
}