2020牛客暑期多校训练营(第二场)F题
程序员文章站
2022-05-12 12:28:19
...
2020牛客暑期多校训练营(第二场)F题
大概题意:输入三个整数m, n, k构建一个m × n的矩阵A,A[m][n]所存的数为m,n的最大公倍数,求矩阵A中所有k × k的子矩阵中的最大值的和。
解题思路:通过组长的分享了解到两次单调队列的解法,思路为先用一个一维队列找出每一行长度为k区间的最大值,在通过另一个二维的队列找出列的最大值,最后求和即为答案。
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int findtheans(int A,int B)
{
int muli=A*B;
while(B)
{
int tmp=A%B;
A=B;
B=tmp;
}
return muli/A;
}
int n, m, k;
int A[5005][5005], tar[5005], a[5005][5005];
int main()
{
cin>>n>>m>>k;
int i,j;
ll ans = 0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
A[i][j]=findtheans(i,j);
}
}
for(i=1;i<=n;i++)
{
int l=0,r=0;
for(j=1;j<=m;j++)
{
while(l<r&&j-tar[l]+1>k)
l ++;
while(l<r&&A[i][tar[r-1]]<=A[i][j])
r --;
tar[r++]=j;
a[i][j]=A[i][tar[l]];
}
}
for(int j=1;j<=m;j++)
{
int l=0,r=0;
for(int i=1;i<=n;i++)
{
while(l<r&&i-tar[l]+1>k)
l++;
while(l<r&&a[tar[r-1]][j]<=a[i][j])
r--;
tar[r++]=i;
a[i][j]=a[tar[l]][j];
}
}
for(int i=k;i<=n;i++)
{
for(int j=k;j<=m;j++)
{
ans+=a[i][j];
}
}
cout <<ans;
return 0;
}
学到:单调队列的运用,滑动窗口
推荐阅读
-
2019牛客暑期多校训练营(第二场)H Second Large Rectangle
-
2020牛客暑期多校训练营(第四场)——Basic Gcd Problem
-
2020牛客暑期多校训练营(第五场)
-
2020牛客暑期多校训练营(第九场) The Flee Plan of Groundhog
-
2020牛客暑期多校训练营Groundhog and Apple Tree(树形dp,贪心)
-
2020暑期牛客多校训练营第九场(K)The Flee Plan of Groundhog(lca,树形dp)
-
2020牛客暑期多校训练营(第二场)Cover the Tree
-
2020牛客暑期多校训练营(第一场)H-Minimum-cost Flow
-
2020牛客暑期多校 第一场 F Infinite String Comparision(字符串)
-
Harmony Pairs 2020牛客暑期多校训练营(第六场)