zoukankan      html  css  js  c++  java
  • 小A的柱状图(栈的应用,找左右边界)

    链接:https://ac.nowcoder.com/acm/contest/549/H
    来源:牛客网

    柱状图是有一些宽度相等的矩形下端对齐以后横向排列的图形,但是小A的柱状图却不是一个规范的柱状图,它的每个矩形下端的宽度可以是不相同的一些整数,分别为a[i],每个矩形的高度是h[i],现在小A只想知道,在这个图形里面包含的最大矩形面积是多少。


    输入描述:

    一行一个整数N,表示长方形的个数
    接下来一行N个整数表示每个长方形的宽度
    接下来一行N个整数表示每个长方形的高度

    输出描述:

    一行一个整数,表示最大的矩形面积
    示例1

    输入

    复制
    7
    1 1 1 1 1 1 1
    2 1 4 5 1 3 3

    输出

    复制
    8

    说明

    样例如图所示,包含的最大矩形面积是8

    备注:

    1≤n≤1e6,1≤a[i]≤100,1≤h[i]≤1e9;
    经典单调栈问题:
    可以看看这里的选线法
    这个题就是找如果这个i点为最小值,所能到达的最左和最右边界

    下面两个思路都是一样的,就是维护一个单调递增的栈(存下标),如果第i个元素比栈顶的小,就一直pop(),然后把这个
    进栈,为什么能pop()呢,对后面没有影响吗,答案是没有的因为如果后面来一个大的,他的左边界最多到i这个元素,如果
    后面来一个比i更小的,那就已知pop(),没什么影响,可以画图看看。
    这是数组模拟
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6+100;
    ll a[maxn];
    ll b[maxn];
    ll l[maxn],r[maxn],sum[maxn];
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];sum[i] = sum[i - 1] + a[i];
        }
        for(int i=1;i<=n;i++){
            cin>>b[i];
              l[i]=r[i] = i;
        }
        for(int i=1;i<= n;i++)
              while(b[l[i]-1]>=b[i]) l[i]=l[l[i]-1];
        for(int i = n; i >= 1; i--)
              while (b[r[i]+1]>=b[i]) r[i]=r[r[i]+1];
        ll ans=0;
        for (int i = 1; i <= n; i++){
        //    cout<<l[i]<<" "<<r[i]<<endl;
          long long x = b[i] * (sum[r[i]] - sum[l[i] - 1]);
          ans=max(ans,x);
          }
          cout<<ans<<endl;
    }

    这是单调栈的

    
    
    #include<bits/stdc++.h>
    typedef long long ll;
    const int maxn =1e6+5;
    using namespace std;
    int n,height[maxn],wid[maxn],le[maxn],ri[maxn],b[maxn];//he代表每个矩形的高度,b代表每个矩形的宽度,wid是从1到第i个矩形的总宽度,le ri能到达最左或者最右的第几个矩形 
    stack<int>q;
    long long ans =0;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>b[i];
            wid[i]=wid[i-1]+b[i];
        }
        for(int i=1;i<=n;i++)
        {
            cin>>height[i];
        }
        for(int i=1;i<=n;i++)//找每个矩形能到达最左 
        {
            while(!q.empty()&&height[q.top()]>=height[i]) q.pop();
            if(q.empty()) le[i]=1;
            else le[i]=q.top()+1;
            q.push(i);
        }
        while(!q.empty()) q.pop();//一定要清栈剩余元素 
        for(int i=n;i>=1;i--) //找每个矩形能到达最右 
        {
            while(!q.empty()&&height[q.top()]>=height[i]) q.pop();
            if(q.empty()) ri[i]=n;
            else ri[i]=q.top()-1;
            q.push(i);
        }
        for(int i=1;i<=n;i++) //找最大值 
        {
            ans =max (ans,(1LL)*(wid[ri[i]]-wid[le[i]-1])*height[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    
    
    
     
    来一个更小的那没有什么
  • 相关阅读:
    标签的讲解
    属性分类
    LeetCode 003. 无重复字符的最长子串 双指针
    Leetcode 136. 只出现一次的数字 异或性质
    Leetcode 231. 2的幂 数学
    LeetCode 21. 合并两个有序链表
    象棋博弈资源
    acwing 343. 排序 topsort floyd 传播闭包
    Leetcode 945 使数组唯一的最小增量 贪心
    Leetcode 785 判断二分图 BFS 二分染色
  • 原文地址:https://www.cnblogs.com/lipu123/p/14327600.html
Copyright © 2011-2022 走看看