zoukankan      html  css  js  c++  java
  • HDU

    题意:求一个直方图中最大矩形的面积。

    很经典的一道问题了吧,可以用单调栈分别求出每个柱子左右两边第一个比它低的柱子(也就相当于求出了和它相连的最后一个比它高的柱子),确定每个柱子的左右边界,每个柱子的高度乘上左右边界的宽度求最大值就行了。

    也可以用笛卡尔树上dp的方法搞一搞,即用每个结点权值和所在子树的大小分别表示高度和宽度。(建笛卡尔树的过程也用到了单调栈,作用是维护右链)

    单调栈做法:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int a[N],n,sta[N],L[N],R[N],tp;
     6 
     7 int main() {
     8     while(scanf("%d",&n)&&n) {
     9         a[0]=a[n+1]=-1;
    10         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    11         sta[tp=0]=0;
    12         for(int i=1; i<=n; ++i) {
    13             for(; a[sta[tp]]>=a[i]; --tp);
    14             L[i]=sta[tp]+1,sta[++tp]=i;
    15         }
    16         sta[tp=0]=n+1;
    17         for(int i=n; i>=1; --i) {
    18             for(; a[sta[tp]]>=a[i]; --tp);
    19             R[i]=sta[tp]-1,sta[++tp]=i;
    20         }
    21         ll ans=0;
    22         for(int i=1; i<=n; ++i)ans=max(ans,(ll)a[i]*(R[i]-L[i]+1));
    23         printf("%lld
    ",ans);
    24     }
    25     return 0;
    26 }

    笛卡尔树做法:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int n,a[N];
     6 struct Cartesian {
     7     static const int N=1e5+10;
     8     int ls[N],rs[N],val[N],siz[N],sta[N],tp,tot;
     9     int newnode(int x) {int u=tot++; ls[u]=rs[u]=siz[u]=0,val[u]=x; return u;}
    10     void build(int* a,int n) {
    11         tot=0,newnode(0),sta[tp=0]=newnode(-1);
    12         for(int i=0; i<n; ++i) {
    13             int u=newnode(a[i]);
    14             for(; val[sta[tp]]>=val[u]; --tp);
    15             ls[u]=rs[sta[tp]],rs[sta[tp]]=u;
    16             sta[++tp]=u;
    17         }
    18     }
    19     void dfs(int u=1) {
    20         if(!u)return;
    21         dfs(ls[u]),dfs(rs[u]);
    22         siz[u]=siz[ls[u]]+siz[rs[u]]+1;
    23     }
    24 } cart;
    25 
    26 int main() {
    27     while(scanf("%d",&n)&&n) {
    28         for(int i=0; i<n; ++i)scanf("%d",&a[i]);
    29         cart.build(a,n);
    30         cart.dfs();
    31         ll ans=0;
    32         for(int i=0; i<cart.tot; ++i)ans=max(ans,(ll)cart.siz[i]*cart.val[i]);
    33         printf("%lld
    ",ans);
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    线程同步技术
    线程调用
    进程与线程
    网络配置
    vi
    文件系统
    系统管理命令
    Linux常用命令
    Shell编程
    新版chrome touch警告处理办法
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10540265.html
Copyright © 2011-2022 走看看