2020牛客暑期多校训练营(第二场)——F题(Fake Maxpooling)


题目链接

题目描述

Given a matrix of size n×m and an integerk, where A i,j=lcm(i,j), the least common multiple of i and j. You should determine the sum of the maximums among all k×k submatrices.

输入描述

Only one line containing three integers n,m,k(1≤n,m≤5000,1≤k≤min{n,m}).

输出描述

Only one line containing one integer, denoting the answer.

样例输入

3 4 2

样例输出

38

说明

在这里插入图片描述

题解

给定大小为n×m的矩阵和整数k,其中A {i,j} =lcm(i,j),是i和j的最小公倍数。找到所有大小为k×k的子矩阵中的最大值之和。下面是官方题解:
在这里插入图片描述

单调队列

单调队列:队列里的元素都是单调的。普通队列只允许先进先出,单调队列在入队时先进行判断———入队后是否是单调的,如果是就直接入队,如果不是就先从尾部把使它不单调的元素弹出。可以使用deque(双向队列)来控制进出。(如果不懂,可以点此

代码

#include<bits/stdc++.h>
using namespace std;
int a[5005][5005],b[5005][5005];
deque<int>q;
int main()
{
    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(!a[i][j]) for(int k=1;k*i<=n&&k*j<=m;k++) a[k*i][k*j]=i*j*k;
    for(int i=1;i<=n;i++)
    {
        while(!q.empty()) q.pop_back();
        q.push_back(0);
        for(int j=1;j<k;j++)
        {
            while(q.size()&&a[i][q.front()]<=a[i][j]) q.pop_back();
            q.push_back(j);
        }
        for(int j=k;j<=m;j++)
        {
            while(q.size()&&q.front()<=j-k) q.pop_front();
            while(q.size()&&a[i][q.back()]<=a[i][j]) q.pop_back();
            q.push_back(j);
            b[i][j]=max(b[i][j],a[i][q.front()]);
        }
    }
    long long ans=0;
    for(int j=k;j<=m;j++)
    {
        while(!q.empty()) q.pop_back();
        q.push_back(0);
        for(int i=1;i<k;i++)
        {
            while(q.size()&&b[q.front()][j]<=b[i][j]) q.pop_back();
            q.push_back(i);
        }
        for(int i=k;i<=n;i++)
        {
            while(q.size()&&q.front()<=i-k) q.pop_front();
            while(q.size()&&b[q.back()][j]<=b[i][j]) q.pop_back();
            q.push_back(i);
            ans+=b[q.front()][j];
        }
    }
    printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/cxkdad/article/details/107340773