1. 程式人生 > >HDU - 1506 Largest Rectangle in a Histogram (單調棧/笛卡爾樹)

HDU - 1506 Largest Rectangle in a Histogram (單調棧/笛卡爾樹)

return col 一道 scan 卡爾 左右 build new \n

題意:求一個直方圖中最大矩形的面積。

很經典的一道問題了吧,可以用單調棧分別求出每個柱子左右兩邊第一個比它低的柱子(也就相當於求出了和它相連的最後一個比它高的柱子),確定每個柱子的左右邊界,每個柱子的高度乘上左右邊界的寬度求最大值就行了。

也可以用笛卡爾樹上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\n",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\n",ans);
34     }
35     return 0;
36 }

HDU - 1506 Largest Rectangle in a Histogram (單調棧/笛卡爾樹)