懶得放題目鏈結了
qwq(果然我是菜的真實,單調棧都不會,gg)
首先我們看到這個題。
應該會想到就是直接枚舉行,然後計算當前行的答案。
那現在,對於每一行來說,如果我們能夠維護出\(h[j]\)表示第\(j\)列的最近的乙個不合法的位置。
那麼實際上就是求一堆矩形的並的乙個圖形中。
有多少個矩形。
首先考慮暴力,我們可以直接列舉每一列,然後列舉他前面的列進行計算,這個複雜度是\(o(n^3)\)的。
那我們應該怎麼去優化他呢?
這時候就需要單調棧了!
我們用單調棧維護乙個單調上公升的序列。
通過列舉每個列,算以\((i,j)\)這個點為右下角的\(ans\)。
然後我們通過維護乙個\(now\)來表示已經處理過的值,每次更新
然後\(ans+=now\)
具體應該怎麼做呢?
對於每次加入,我們嘗試彈出棧裡面的元素,然後刪除他和他之前那個元素的位置之間的貢獻(也就是他們兩個之間的距離乘上棧頂元素的高度!)
(其實就相當於中間一段矩陣都是不合法的,沒法選)
最後加入的時候,記得加入當前列與棧頂之間的貢獻(就是當前列和棧頂元素之間的距離乘上當前列的\(i-h[j]\))
表示中間一段矩形都是可以算的。『
這裡運用了乙個很巧妙的思路就是每次只處理相鄰兩個元素的貢獻
具體實現還是看**吧
#include#include#include#include#include#include#include#includeusing namespace std;
inline int read()
while (isdigit(ch))
return x*f;
}const int maxn = 1e6+1e2;
struct node
;node a[maxn];
int n,m;
char s[3010][3010];
int h[maxn];
long long ans,now;
int main()
now+=(j-a[top].pos)*(i-h[j]);///計算當前元素和棧頂之間對ans的貢獻
a[++top].val=h[j];
a[top].pos=j;
ans+=now;
}} cout
}
洛谷 發射站 單調棧
題解 本題主要考查單調棧。簡要題意 乙個發射站會向左邊最近的比它高的和右邊比它高的其他發射站發射能量,求接收最多能量的發射站接收的能量是多少。1.單調棧 維護乙個單調遞增的棧,如果準備入棧的元素大於棧頂元素,那麼新元素能量加上棧頂元素能量,退棧。如下 include include includeu...
洛谷P2216 理想的正方形 單調佇列
有乙個n m n times m n m的整數組成的矩陣,現請你從中找出乙個k k k times k k k的正方形區域,使得該區域所有數中的最大值和最小值的差最小。樸素的想法是直接暴力列舉區間,然後列舉其中的每一位。時間複雜度o n m k2 o nm times k 2 o nm k 2 另一...
洛谷P2216 理想的正方形 單調佇列
給出乙個n m n mn m的矩陣,現在要你從裡面找出乙個k k k kk k的矩陣,使得這個矩陣的最大值減去最小值最大。n,m 1e3 n,m leq1e3 n,m 1e 3。如果只是乙個序列,維護長度為k kk的區間的最大值減去最小值。直接用兩個單調佇列分別維護這個滑動視窗即可。那麼要維護乙個矩...