题目大意:给一个n×m的矩阵,对于第i行第j列的等于i与j的最小公倍数,求该矩阵中每个k×k大小的子矩阵中最大值的和
时间给的很充裕且矩阵为静态,可通过两次单调队列求得k×k范围内的最大值
#include<iostream> #include<cstdio> using namespace std; int Num[5005][5005]; int gcd(int a,int b) { if(!b)return a; return gcd(b,a%b); } struct Node{ int val,time; }; int amx1[5005][5005]; int main() { int n,m,k; long long ans=0; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;++i) { Node q1[10005]={0}; int head=5001,tail=5001; for(int j=1;j<=m;++j) { Num[i][j]=i*j/gcd(i,j); while(head!=tail&&j-q1[head-1].time>=k)head--; while(head!=tail&&q1[tail].val<Num[i][j])tail++; tail--; q1[tail].time=j; q1[tail].val=Num[i][j]; amx1[i][j]=q1[head-1].val; } } for(int j=1;j<=m;++j) { Node q1[10005]={0}; int head=5001,tail=5001; for(int i=1;i<=n;++i) { while(head!=tail&&i-q1[head-1].time>=k)head--; while(head!=tail&&q1[tail].val<amx1[i][j])tail++; tail--; q1[tail].time=i; q1[tail].val=amx1[i][j]; if(i>=k&&j>=k)ans+=q1[head-1].val;; } } printf("%lld",ans); return 0; }