题目大意:给一个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;
}