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

Fake Maxpooling

https://ac.nowcoder.com/acm/contest/5667/F

题目描述

  Given a matrix of size and an integer , where , the least common multiple of and . You should determine the sum of the maximums among all submatrices.

输入描述

  Only one line containing three integers .

输出描述

  Only one line containing one integer, denoting the answer.

示例1

输入

3 4 2

输出

38  

说明

  The given matrix is: .
  The maximums among all submatrices are respectively, and their sum is .

分析

  要求所有边长为 的正方形区域内的最值,可以看作将滑动窗口由一维的数轴扩展到了二维矩阵上。
  首先对于每一行利用单调队列求出位于 时, 区域内的最大值,用 表示。然后,遍历每一列,利用单调队列求出位于 时, 区域内 的最大值,用 表示(直接赋值于 );由于 已经是 的最大值,所以第二次纵向求区间最大值后, 已经表示由 为左上角, 为右下角的正方形区域内的最大值。
  至此,求出了所有边长为 的正方形区域内的最值。

代码

/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第二场) Problem F
Date: 8/11/2020
Description: Monotonous Queue
*******************************************************************/
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5003;
int n,m,k;
int ans[N][N];
int a[N][N];
int q[N];
int head,tail;
int main()
{
    int i,j;
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            a[i][j]=i*j/__gcd(i,j);
        }
    }
    for(i=1;i<=n;i++)
    {
        //第i行区间长度为k的区间最大值
        head=1;
        tail=0;
        for(j=1;j<=m;j++)
        {
            while(head<=tail&&a[i][q[tail]]<=a[i][j]) tail--;
            q[++tail]=j;
            while(head<=tail&&q[head]<=j-k) head++;
            if(j>=k) ans[i][j-k+1]=a[i][q[head]];
        }
    }
    for(j=1;j<=m;j++)
    {
        //考察每一列
        //已经是从i开始的横向长度为k的区间最大值
        //求从第j列开始的纵向长度为k的区间最大值
        //便有从(i,j)开始的区域边长为k的区间最大值
        head=1;
        tail=0;
        for(i=1;i<=n;i++)
        {
            while(head<=tail&&ans[q[tail]][j]<=ans[i][j]) tail--;
            q[++tail]=i;
            while(head<=tail&&q[head]<=i-k) head++;
            if(i>=k) ans[i-k+1][j]=ans[q[head]][j];
        }
    }
    long long tot=0;
    for(i=1;i<=n-k+1;i++)
    {
        for(j=1;j<=m-k+1;j++)
        {
            tot+=ans[i][j];
        }
    }
    cout<<tot<<endl;
    return 0;
}
牛客暑期多校训练营题解 文章被收录于专栏

收集牛客暑期多校训练营的题解

全部评论

相关推荐

点赞 评论 收藏
分享
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务