問題描述:
柱狀圖是有一些寬度相等的長方形下端對齊後橫向排列得到的圖形。現在有n個由寬度為1,高度分別為h1,h2,..hn的長方形從左到右依次排列組成的柱狀圖。問裡面包含的長方形的最大面積是多少?
分析:
最容易想到的方法是:討論左端l和右端r。如果確定了長方形的左端l和右端r,那麼最大的可能高度就是min(hi|l<=i<=r).但這樣的話時間複雜度為o(n^3)。如果對區間的最小值優化的話,可以把時間複雜度降為o(n^2),但是還是不夠。
所以我們從每個hi討論。包含的hi的長方形的最大的面積的左端點為l,那麼一定有第l-1個柱狀體的高度一定小於hi,並且l到i的柱狀體的高度一定都大於等於hi。同理包含的hi的長方形的最大的面積的右端點為r,那麼一定有第r+1個柱狀體的高度一定小於hi.
綜上所述,所以我們要求出每個位置在i前面且高度小於hi的最近的l,和後面最近的r。我們記為l[i]和r[i]。如果求出了l[i]和r[i]那麼最大面積就是max(hi*(r[i]-l[i]))。
用單調棧就可以很方便的求出l[i],r[i]。思想如下:
首先第乙個棧,初始化為空。然後不斷增加i(下標)的值,並維護這個棧使他按照下面的儲存用於維護推算出後面的l值得元素。
設在棧裡的元素從上到下值為xi,則xi>xi+1且hxi>hxi+1
在計算l[i]時,首先當棧頂元素j滿足hj>=hi,則不斷取出棧頂的元素。如棧為空則l[i]=0,若hj
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 100010;
int n;
int h[maxn],l[maxn],r[maxn];
int st[maxn];
void solve()
t = 0;
for(int i=n-1;i>=0;i--)
long
long ans = 0;
for(int i=0;ilong
long)h[i]*(r[i]-l[i]));
}printf("%lld\n",ans);
}int main()
return
0;}
2016大連網路賽
function
題意:
給你乙個n個數的數列,詢問(l,r):a[l]%a[l+1]…..%a[r]的值。
分析:
我可可以按照題意乙個乙個算,但是太耗時了。那怎麼辦呢?當我們用第l個數去模後面的數k後,那麼再去模後面的比k大的數就沒有意義了。所以我只用關心後面比k小的數。所以我們用單調棧去儲存每個位置後面值比他小的第乙個位置pos即可。
ac**:
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 100005;
int a[maxn];
int pos[maxn];//記錄結果
int s[maxn];//單調棧
int main()
printf("%d\n",ans);}}
return
0;}
單調棧的應用
筆者在做leecode的題 求柱形的最大面積 時,接觸到了單調棧這一資料結構,經過研究發現,單調棧是乙個比較簡單的資料結構,但是要靈活運用卻十分不簡單。單調遞增棧 資料出棧的序列為單調遞增序列 單調遞減棧 資料出棧的序列為單調遞減的序列 描述 有n個人站隊,所有的人全部向右看,個子高的可以看到個子低...
單調棧的應用
單調棧 故名思意,棧中元素是單調遞增 不減 或者是單調遞減 不增 leetcode 85 最大矩形 是乙個應用單調棧的好題目。題目分析 要找到乙個最大矩形,當然可以暴力解法,這個思路簡單,這裡就不多說了。該如何使用單調棧解決問題呢?可以先嘗試地做leetcode 84 柱狀圖中的最大矩形 這個是85...
單調棧的應用
單調棧的使用 單調棧的分類 單調遞增棧 單調遞減棧 所謂的遞增和遞減,相對的是 棧頂 棧底的資料大小表示 棧頂 棧底 從小到大 單調遞增 棧頂 棧底 從大到小,單調遞減 單調棧的實現方式 舉例用單調遞增棧 從後向前進行儲存,並讀取。如果棧空入棧 棧非空,此時棧頂元素 入棧元素,入棧 棧非空,此時棧頂...