先对每一行求一遍滑动窗口,列数变为(列数-k+1)
再对每一列求一遍滑动窗口,行数变为(行数-k+1)
剩下的就是每一个窗口里的最大值啦
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
typedef long double ld;
const int N = 5010;
int n, m, k;
int a[N][N];
int q[N], hh, tt;
int main()
{
IOS
cin >> n >> m >> k;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] = i * j / __gcd(i, j);
for(int i = 1; i <= n; i ++)
{
hh = 0, tt = -1;
for(int j = 1; j <= m; j ++)
{
if(hh <= tt && q[hh] < j - k + 1)hh ++;
while(hh <= tt && a[i][q[tt]] <= a[i][j])tt --;
q[++ tt] = j;
if(j >= k)a[i][j - k + 1] = a[i][q[hh]];
}
}
m = m - k + 1;
for(int j = 1; j <= m; j ++)
{
hh = 0, tt = -1;
for(int i = 1; i <= n; i ++)
{
if(hh <= tt && q[hh] < i - k + 1)hh ++;
while(hh <= tt && a[q[tt]][j] <= a[i][j])tt --;
q[++ tt] = i;
if(i >= k)a[i - k + 1][j] = a[q[hh]][j];
}
}
n = n - k + 1;
ll ans = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
ans += a[i][j];
cout << ans;
return 0;
}