牛客多校2 - Fake Maxpooling(线性递推gcd+单调队列)
生活随笔
收集整理的這篇文章主要介紹了
牛客多校2 - Fake Maxpooling(线性递推gcd+单调队列)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一個矩陣 A 的大小,規(guī)定其元素 A[ i ][ j ] = lcm( i , j ) ,再給出一個 k ,求所有大小為 k * k 的子矩陣中的最大值之和
題目分析:題目時限給了三秒,可以直接 n * m * logn 去求出矩陣 A ,但題解提供了一種可以線性求解 gcd 的方法,所以可以優(yōu)化掉一層 log,在求出矩陣 A 后,可以對于每一行,利用單調(diào)隊列維護區(qū)間最大值,mmax[ i ][ j ] 記錄 A[ i ][ j - k ] : A[ i ][ j ] 的最大值,最后再利用單調(diào)隊列,求解一下 mmax[ i - k ][ j ] : mmax[ i ][ j ] 的最大值就是子矩陣 ( i - k , j - k ) ~ ( i , j ) 的最大值了,區(qū)間維護最大值的代碼可以參考經(jīng)典例題:滑動窗口
另外這個題目有點卡內(nèi)存,如果是 5000 * 5000 的數(shù)組的話,最多只能開兩個,所以可以將 A 數(shù)組與 mmax 數(shù)組進行一個復(fù)用
代碼:
#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<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=5e3+100;int g[N][N];int mmax[N][N];//mmax[i][j]:max(maze[i][j-k]:maze[i][j])struct Node {int val,id;Node(int val,int id):val(val),id(id){} };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);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(!g[i][j])for(int k=1;k*i<=n&&k*j<=m;k++)g[k*i][k*j]=k,mmax[k*i][k*j]=i*j*k;for(int i=1;i<=n;i++){deque<Node>q;for(int j=1;j<=k-1;j++){while(q.size()&&q.back().val<=mmax[i][j])//將比當前值小的數(shù)全刪掉(尾部)q.pop_back();q.push_back(Node(mmax[i][j],j));}for(int j=k;j<=m;j++){int left=j-k+1;while(q.size()&&q.back().val<=mmax[i][j])//將比當前值小的數(shù)全刪掉(尾部)q.pop_back();q.push_back(Node(mmax[i][j],j));while(q.size()&&q.front().id<left)//將過期的值刪掉(頭部)q.pop_front();mmax[i][j]=q.front().val;}}LL ans=0;for(int j=k;j<=m;j++){deque<Node>q;for(int i=1;i<=k-1;i++){while(q.size()&&q.back().val<=mmax[i][j])//將比當前值小的數(shù)全刪掉(尾部)q.pop_back();q.push_back(Node(mmax[i][j],i));}for(int i=k;i<=n;i++){int left=i-k+1;while(q.size()&&q.back().val<=mmax[i][j])//將比當前值小的數(shù)全刪掉(尾部)q.pop_back();q.push_back(Node(mmax[i][j],i));while(q.size()&&q.front().id<left)//將過期的值刪掉(頭部)q.pop_front();ans+=q.front().val;}}printf("%lld\n",ans);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的牛客多校2 - Fake Maxpooling(线性递推gcd+单调队列)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客多校2 - Cover the Tr
- 下一篇: 牛客多校2 - Just Shuffle