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;
    }
    
    
    
     
    来一个更小的那没有什么
  • 相关阅读:
    python3-day6(模块)
    python3-day5(模块)
    python3-day4(re正则表达式,冒泡)
    python3-day4(递归)
    python3-day4(装饰器)
    python3-day3(内置函数)
    python3-day3(函数-参数)
    python3-day3(函数-返回值)
    android 开发学习3
    android 开发学习2
  • 原文地址:https://www.cnblogs.com/lipu123/p/14327600.html
Copyright © 2011-2022 走看看