CodeForces - 1323B Count Subrectangles(思维)
題目鏈接:點(diǎn)擊查看
題目大意:給出一個(gè)數(shù)組 a 和數(shù)組 b 只由 0 和 1 構(gòu)成,構(gòu)造出矩陣 maze[ x?][ y?] = a[ x ] * b[ y ],顯然maze矩陣同樣只由 0 和 1 構(gòu)成,現(xiàn)在要求面積為 k 的子矩陣中,有多少個(gè)全部為 1?
題目分析:再次感覺(jué)難度大于 C 題的一道 B 題。。考察的方面很綜合,不知道如何分類,就暫且分為思維吧,首先排除n*m*n*m的暴力,接下來(lái)一步一步考慮,因?yàn)槊娣e為 k 的子矩陣,換一種說(shuō)法,假設(shè)子矩陣的大小為 x * y ,則必須滿足 x * y == k 的子矩陣才可能滿足條件,所以不難想到要對(duì)面積 k 進(jìn)行因數(shù)分解,sqrt( k )的時(shí)間復(fù)雜度預(yù)處理出 k 的所有因數(shù)作為子矩陣的長(zhǎng)和寬,對(duì)于每一對(duì)可行的長(zhǎng)和寬 ( x , y ) 來(lái)說(shuō),都需要計(jì)算其貢獻(xiàn),接下來(lái)說(shuō)的內(nèi)容可能有點(diǎn)抽象,后面我會(huì)舉例子說(shuō)明的。現(xiàn)在的問(wèn)題轉(zhuǎn)換為了,給出指定大小的子矩陣 ( x , y ) ,如何計(jì)算出其出現(xiàn)次數(shù),通過(guò)觀察樣例給出的矩陣可以發(fā)現(xiàn),假設(shè)某個(gè)子矩陣的左上角端點(diǎn)為( x1 , y1 ),右下角端點(diǎn)為( x2 , y2 ),若該子矩陣想要全部為 1 的話,那么數(shù)組 a[ x1 ] ~ a[ x2 ] 以及 b[ y1 ] ~ b[ y2 ] 的這兩段連續(xù)區(qū)間內(nèi)必須全部為 1 才行,這樣就可以將數(shù)組 a 以及數(shù)組 b 轉(zhuǎn)換為連續(xù)的 1 儲(chǔ)存了,比如數(shù)組 a 原本為 1011011101 ,那么轉(zhuǎn)換后就變?yōu)榱?1,2,3,1 了,我們記為 aa 數(shù)組和 bb 數(shù)組,這樣轉(zhuǎn)換后有什么用呢?剩下的其實(shí)就可以排列組合計(jì)算答案了,還是以大小為( x , y )的子矩陣為例,我們遍歷一遍 aa 數(shù)組,可以對(duì)大小為 x * y 的子矩陣做出貢獻(xiàn),那么必須滿足連續(xù)的行數(shù)大于等于 x 才行,通過(guò)平移可以知道,貢獻(xiàn)就是 aa[ i ] - x + 1 了,遍歷一遍數(shù)組aa后,可以計(jì)算出有多少種行可以做出貢獻(xiàn),同理遍歷一遍 bb 數(shù)組后計(jì)算出有多少列可以做出貢獻(xiàn),相乘就是總貢獻(xiàn)了
下面舉一個(gè)例子,就拿樣例為例,a 數(shù)組為 1 0 1,轉(zhuǎn)換為 aa 數(shù)組也就變成了 1,1
b 數(shù)組為 1 1 1,轉(zhuǎn)換為 bb 數(shù)組也就變成了 3
以大小為 ( 1 , 2 ) 的子矩陣為例,我們需要在 aa 數(shù)組中找到有多少個(gè)連續(xù)的行滿足 aa[ i ] >= 1,顯然有兩個(gè)
接下來(lái)需要在 bb 數(shù)組中找到有多少個(gè)連續(xù)的列,滿足 bb[ i ] >= 2 ,因?yàn)?bb 數(shù)組只有一個(gè)元素,且其值為 3 ,那么對(duì)列的貢獻(xiàn)也就是 2 了,因?yàn)榭梢赃@樣選:(選橙色的列)
1 1 1
也可以這樣選:
1 1 1
綜上,對(duì)于子矩陣 ( 1 , 2 ) 的貢獻(xiàn)為 2 * 2 = 4
總時(shí)間復(fù)雜度為 sqrt( n * m )*( n + m ),我用了unordered_map稍加優(yōu)化,而且sqrt(n*m)應(yīng)該也不會(huì)拉滿,所以評(píng)測(cè)機(jī)給出的反饋是十分不錯(cuò)的
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=4e4+100;int a[N],b[N];vector<pair<int,int>>node;void init(int k) {for(int i=1;i*i<=k;i++){if(k%i==0){node.push_back(make_pair(i,k/i));if(i!=k/i)node.push_back(make_pair(k/i,i));}} }unordered_map<int,int>A,B;void solve(int a[],int n,unordered_map<int,int>& mp) {int pos=1,cnt=0;while(pos<=n){while(a[pos]){pos++;cnt++;}if(cnt){mp[cnt]++;cnt=0;}pos++;} }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,k;scanf("%d%d%d",&n,&m,&k);init(k);for(int i=1;i<=n;i++)scanf("%d",a+i);for(int i=1;i<=m;i++)scanf("%d",b+i);solve(a,n,A);//預(yù)處理出aa數(shù)組和bb數(shù)組,存放在unordered_map中solve(b,m,B);LL ans=0;for(int k=0;k<node.size();k++)//遍歷每對(duì)因子{int x=node[k].first,y=node[k].second;LL xx=0,yy=0;for(auto it:A)//行貢獻(xiàn)if(it.first>=x)xx+=it.second*(it.first-x+1);for(auto it:B)//列貢獻(xiàn)if(it.first>=y)yy+=it.second*(it.first-y+1);ans+=xx*yy;//累加貢獻(xiàn)}printf("%lld\n",ans);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的CodeForces - 1323B Count Subrectangles(思维)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HDU - 5306 Gorgeous
- 下一篇: CodeForces - 1323C U