CF627E Orchestra(尺取法 鍊錶)

2022-05-14 13:48:13 字數 1006 閱讀 6005

點此看題面

大致題意:給定乙個\(r\times c\)的矩陣,其中有\(n\)個\(1\)。問有多少子矩陣包含至少\(k\)個\(1\)。

不得不說這題的思想是非常巧妙的。

有乙個顯而易見的\(o(r^2c)\)暴力,即枚舉子矩陣上下邊界,然後用尺取法掃一遍。

現在我們考慮仍舊列舉上邊界,然後從下往上列舉下邊界,每次移動下邊界時求出刪去這一層點給答案帶來的變化。

刪去乙個點,因此而減少的貢獻就是所有包含它所在列且恰好包含\(k\)個點的矩陣個數。

我們用鍊錶來維護有點的每一列,那麼暴力找出這些矩陣最多也就只要往前跳\(k\)次,同時維護好右邊界即可。

總複雜度\(o(r^2k)\)。

\(p.s.\) 寫完後發現似乎也可以從上往下列舉下邊界,然後加上每一層點的答案?而且這樣還不用求初始答案了。。。

#include#define tp template#define ts template#define reg register

#define ri reg int

#define con const

#define ci con int&

#define i inline

#define w while

#define n 3000

#define k 10

#define ll long long

using namespace std;

int r,c,n,k,cnt[n+5],pre[n+5],nxt[n+5],c[n+5],v[n+5][n+5];struct p p[n+5];

int main()

!cnt[cur]&&(nxt[pre[cur]]=nxt[cur],pre[nxt[cur]]=pre[cur]);//沒點後從鍊錶中刪去

} }return printf("%lld\n",ans),0;//輸出答案

}