2019牛客多校第八場題解 A

2021-09-26 06:14:29 字數 1220 閱讀 8646

a

給你乙個n*m的01矩陣,求出所有最大全1矩陣的數量,保證任意兩個矩陣不相互包含。

考慮單調棧求最大矩形面積的做法。

對於矩陣

0 0 0 0

0 0 1 0

0 1 1 0

1 1 1 1

0 0 0 0

我們先預處理h[i][j] 為以該行為底的最大高度。那麼我們只要知道這個矩形最左邊的能夠到達的位置l

由於每次我們是從左到右遍歷資料的 所以我們可以確定右邊界r ,並且我們預處理最大高度h[i][j] 

那麼我只要確定下面是否有延伸就可以確定這個矩陣是不是最大的。

也就是說 (r-l+1)!=下一行的相同位置的[l,r]的和。說明這個矩陣是最大的那麼我們累計答案。

建立單調棧的時候如果h[i][j] 大於 s.top() 那麼我們就把 高度為h[i][j],左邊界為j 的元素加入單調棧。

如果h[i][j]<=s.top() 那麼就判斷h[i][j]是否小於s.top() 如果是 就取出棧頂元素。得到左邊界li和高度hi右邊界為

r=j-1 然後我們判斷這個矩陣是不是最大矩陣 如果是則更新答案。然後把棧頂出棧。

直到棧為空 或者棧頂元素等於 h[i][j] ,這時候 我們取出棧頂得到棧頂元素的左邊界li然後,然後把 左邊界為li,高度為

h[i][j]的新元素加入棧。(相當於加入了乙個左邊界為li 高度為hi 的新矩陣) 每次我們每行的單調棧 結尾加入乙個高度為0的元素

h[i][m+1] 這樣 保證棧被清空 並且棧裡面的最後乙個最大矩形也被計算。 

#include#define ll long long

using namespace std;

int n,m,x;

int pre[3010][3010];

int h[3010][3010];

struct node

;int main()

else h[i][j]=x;

pre[i][j]=pre[i][j-1]+x;}}

stacks;

ll ans=0;

int l,r;

for(int i=1;i<=n;i++)

s.pop();

}if(!h[i][j])

}s.push(node);}}

printf("%lld\n",ans);

return 0;

}

2019牛客多校第八場

求所有極大全一矩陣的個數。created by keane on 2019 8 10.include using namespace std typedef long long ll const int n 3050 int a n n int n,m char s n 每個1向下延伸 int dw...

2019 牛客 多校賽 第八場

乙個區間的貢獻為這個區間的不同數字的個數,求所有子區間的貢獻和 反向思考,計算乙個數字在子區間 現的次數,當區間的左端點在這個數字上一次出現位置和當前位置之間,並且右端點在當前位置之後,這個數字都產生了貢獻,所以當前位置的數字的貢獻就是左端點數量 右端點數量,然後遍歷一遍。include defin...

牛客多校第八場

簽到題,可真短。題意 給n個數,對於每個連續子串行求區間內不同數字的個數的和。做法 一開始列舉每個區間的右端點i,判斷每個數字在區間左端點為1 i這個範圍內對右端點i的貢獻,然後累加答案,然後超時了。之後想到,每次變化範圍只會變乙個數字,只會改變乙個數字的貢獻,所以開了乙個sum記錄所有數字的貢獻就...