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;
}
牛客暑期多校训练营题解 文章被收录于专栏

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

全部评论

相关推荐

点赞 评论 收藏
分享
2本硕,在这一个下午真的绷不住了,浪费了太多时间,现在的技术栈还停在C语言和stm32上,找嵌入式的实习面试被拷打,找杭州的一个也找不到,真的心里难受,linux没学过,研二了开始慌了。
一条淡水魚:嵌入式这行的面试我认为实际项目比较重要,技术栈简单的提一嘴就行,面试官在乎的关键点在于你用了这些技术做了哪些工作解决了什么问题,而不是停留在离散的那些个技术栈上,那除了教课没有意义,好比你提到的c语言和32,你用32做过哪些具体的项目?接触过什么外设?使用过哪些公司的SDK?有没有实际产品落地?以及各种只有进入真正的生产环节当中才会积累到的经验......主动去和面试官讨论这些实际的问题,甚至还能就某个具体参数的合理性与他去简单探讨一下,只要技术栈对口,基本上就稳啦~(另外linux和RTOS是嵌入式的标配哦,选一个方向走下去吧)
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务