AOJ-AHU-OJ-558 窃取任务

本文探讨了在信息战中如何高效地选择一个信息接收量最大的塔进行窃取,通过应用单调栈解决双向信息传递的问题。详细介绍了算法实现步骤及优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

窃取任务
Time Limit: 1000 ms   Memory Limit: 64 MB
Description
战争期间,双方互打信息战,我军准备去敌方一条战斗主线上的信息塔窃取他们的信息。敌方的信息塔排成了一条线,每个信息塔都会同时向两侧(两端的塔只向一侧)严格比自己高的最近的信息塔传送信息。现在时间紧迫,我们只能去其中一个信息塔,为了最高效的窃取敌人的信息,我们必须选择其中信息接收量最大的塔。现在请你去执行这个窃取任务。

Input
第1行,一个整数N(1<=N<=50000),表示这条线上有多少个信息塔。
第2行,N个整数h1到hn,其中hi(1<=hi<=2000000)表示第i个塔的高度。

Output
仅1行,一个整数i表示信息接收量最大的塔的编号,如果有多个输出编号最小的。

Sample Input
OriginalTransformed
4
5 2 6 7

Sample Output
OriginalTransformed
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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值