點此看題面
大致題意:給定乙個\(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;//輸出答案
}