单调队列水题 刷广告

【问题描述】

最近,afy决定给TOJ印刷广告,广告牌是刷在城市的建筑物上的,城市里有紧靠着的N个建筑。

afy决定在上面找一块尽可能大的矩形放置广告牌。我们假设每个建筑物都有一个高度,

从左到右给出每个建筑物的高度H1,H2…HN,且0<Hi<=1,000,000,000,并且我们假设每个建筑物的宽度均为1。

要求输出广告牌的最大面积。

【输入文件】

输入文件 ad.in 中的第一行是一个数n (n<= 400,000)

第二行是n个数,分别表示每个建筑物高度H1,H2…HN,且0<Hi<=1,000,000,000。

【输出文件】

输出文件 ad.out 中一共有一行,表示广告牌的最大面积。

【输入样例】

6

5 8 4 4 8 4

【输出样例】

24

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
#define maxn 400000 + 10

int L[maxn], R[maxn];
int pos[maxn];
int a[maxn];
int n;

void get_left()
{
    int head = 1, tail = 0;
    for(int i = 1; i <= n; i++)
    {
        while(head <= tail && a[pos[tail]] >= a[i])
        tail--;
        L[i] = i - pos[tail] - 1;
        pos[++tail] = i;
    }
}

void get_right()
{
    int head = 1, tail = 0;
    pos[tail] = n + 1;
    for(int i = n; i >= 1; i--)
    {
        while(head <= tail && a[pos[tail]] >= a[i])
        tail--;
        R[i] = pos[tail] - i - 1;
        pos[++tail] = i;
    }
}

int main()
{
    while(~scanf("%d", &n))
    {
        memset(L, 0, sizeof L);
        memset(R, 0, sizeof R);
        for(int i = 1; i <= n; i++)
        scanf("%d", a + i);
        get_left();
        get_right();

        long long  ans = -1;
        for(int i = 1; i <= n; i++)
        ans = max(ans, ((long long)L[i] + R[i] + 1) * a[i]);
        printf("%I64d\n", ans);
    }
    return 0;
}

/*

6
5 8 4 4 8 4

*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 13:42:18

单调队列水题 刷广告的相关文章

hdu 3530 单调队列水题

给你一个数列找到最长的子序列   中的最大值减最小值值m   k之间 建立两个单调队列   一个递增    一个递减    当两个队首满足情况是就进行比较 找到最大值 当不满足是旧的移动队首      怎样移??? 移动队首id较小的一个 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int max(int a,int b) { return a>b?a:b

hdu 3706 单调队列水题

#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[1000001],id[1000001]; int main() { int n,A,B; int i,j; while(~scanf("%d%d%d",&n,&A,&B)) { int front=0; int top=0; __int64 x=1,sum=

Sliding Window POJ - 2823 单调队列模板题

Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间最小值 就是维护一个单调递增的序列 对于样例 8 3 1 3 -1 -3 5 3 6 7 我们先模拟一遍 1.队列为空 1 进队 队列:1 2.3>队尾元素 3 进队 队列: 1 3 3.-1小于队尾元素,一直从尾部出队知道找到比-1小的元素或者队列为空 队列:-1 当队列中元素大于m的时候从队头删

HUD 3706 单调队列简单题

Problem Description Give you three integers n, A and B. Then we define Si = Ai mod B and Ti = Min{ Sk | i-A <= k <= i, k >= 1} Your task is to calculate the product of Ti (1 <= i <= n) mod B. 不描述题意了,三行英文挺明了的,今天刚学单调队列,自己模拟一下过了这题 单调队列 1,永远保持队

poj 2823 单调队列裸题

两个队列分别维持最大和最小 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct node { int mi,ma; }num[1000010]; int sax[1000010],sin[1000010]; int ida[1000010],idi[1000010]; int main() { int n,m,i,j,k,a; while(~scanf(&

【Poj1003】刷水题刷的不亦乐乎

输入一个长度 利用循环计算需要多少张卡片 输出时注意i是从2开始,最后结束时i是多加了个1 所以输出i-2 #include<iostream> using namespace std; int main(){ double l; while(cin>>l && l!=0.0){ double lon=0.0; int i=2; for(;lon<l;i++) lon+=1.0/i; cout<<i-2<<" card(s)\

hdu3415(单调队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415 题意:一个长度为n包含正负整数的数环,即第1个的左边是第n个.从中选一个不超过k的序列,使得序列和最大,最大值相同选开始点最小的,开始点相同选长度最小的. 分析:单调队列维护在k个数之内的最小值的下标,然后一直扫一遍就行了,只要懂单调队列这题就是水题了. #include <cstdio> #include <cstring> #include <cmath> #in

【单调队列】POJ2823-Sliding Window

单调队列经典题之一. [思路] 设置两个单调队列分别记录最大值和最小值.对于每一个新读入的数字,进行两次操作(对于求最大值和最小值中的某一个而言),一是若队首不在滑窗范围内则删去:二是删去队末比当前值小(或大)的值,并将当前值插入对尾.每一次的最小(大)值就是当前单调队列的队首. [错误点] 一定要写while (scanf("%d%d",&n,&k)!=EOF),否则会WA. 我一开始的做法是这样的:先把第一个数插入队尾,再从第二个数开始进行后续操作.这样的问题在于如

POJ 1742 Coins ( 单调队列解法 )

题目链接~~> 做题感悟:第一次做的时候用的二进制优化,但是没注意到是险过,so也没去看单调队列的解法. 解题思路: 如果你做过单调队列的题,或者看过相关的博客就好理解这题了,博客.再加上这题体积与价值相等那么就更好做了.只有 j %v[ i ] 余数相同的才可以同时处理(j 指的是某个体积的值),在计算某个数的时候,只要计算前面的相同的余数中(在个数限制内)是否有 true(有放满的) 就可以了. 代码: #include<iostream> #include<sstream&g