【单调队列】第十四届蓝桥杯省赛C++ C组 Java C组/研究生组 Python A组《子矩阵》(C++)

【题目描述】

给定一个 n×m (n 行 m 列)的矩阵。

设一个矩阵的价值为其所有数中的最大值和最小值的乘积。

求给定矩阵的所有大小为 a×b (a 行 b 列)的子矩阵的价值的和。

答案可能很大,你只需要输出答案对 998244353 取模后的结果。

【输入格式】

输入的第一行包含四个整数分别表示 n,m,a,b,相邻整数之间使用一个空格分隔。

接下来 n 行每行包含 m 个整数,相邻整数之间使用一个空格分隔,表示矩阵中的每个数

【输出格式】

输出一行包含一个整数表示答案。

【数据范围】

对于 40% 的评测用例,1≤n,m≤100;

对于 70% 的评测用例,1≤n,m≤500;

对于所有评测用例,1≤a≤n≤1000,1≤b≤m≤1000,1≤Ai,j≤

【输入样例】

2 3 1 2
1 2 3
4 5 6

【输出样例】

58

【样例解释】

1×2+2×3+4×5+5×6=58。

【代码】

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;
const int N = 1010, MOD = 998244353;

int n, m, A, B;
int w[N][N];
int rmax[N][N], rmin[N][N];
int q[N];

void get_max(int a[], int b[], int tot, int k)
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && q[hh] <= i - k) hh ++ ;
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[ ++ tt] = i;
        b[i] = a[q[hh]];
    }
}

void get_min(int a[], int b[], int tot, int k)
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && q[hh] <= i - k) hh ++ ;
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[ ++ tt] = i;
        b[i] = a[q[hh]];
    }
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &A, &B);
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            scanf("%d", &w[i][j]);

    for (int i = 0; i < n; i ++ )
    {
        get_max(w[i], rmax[i], m, B);
        get_min(w[i], rmin[i], m, B);
    }

    int res = 0;

    int a[N], b[N], c[N];
    for (int i = B - 1; i < m; i ++ )
    {
        for (int j = 0; j < n; j ++ ) a[j] = rmax[j][i];
        get_max(a, b, n, A);
        for (int j = 0; j < n; j ++ ) a[j] = rmin[j][i];
        get_min(a, c, n, A);
        for (int j = A - 1; j < n; j ++ )
            res = (res + (LL)b[j] * c[j]) % MOD;
    }

    printf("%d\n", res);
    return 0;
}
相关推荐
优雅的潮叭4 小时前
c++ 学习笔记之 shared_ptr
c++·笔记·学习
多米Domi0114 小时前
0x3f第33天复习 (16;45-18:00)
数据结构·python·算法·leetcode·链表
SunkingYang5 小时前
QT中使用Lambda表达式作为槽函数用法,以及捕获列表和参数列表用法与区别
c++·qt·用法·lambda表达式·捕获列表·槽函数·参数列表
微露清风5 小时前
系统性学习C++-第二十二讲-C++11
java·c++·学习
罗湖老棍子5 小时前
【例4-11】最短网络(agrinet)(信息学奥赛一本通- P1350)
算法·图论·kruskal·prim
方圆工作室5 小时前
【C语言图形学】用*号绘制完美圆的三种算法详解与实现【AI】
c语言·开发语言·算法
Lips6115 小时前
2026.1.16力扣刷题
数据结构·算法·leetcode
代码村新手6 小时前
C++-类和对象(中)
java·开发语言·c++
kylezhao20196 小时前
C# 文件的输入与输出(I/O)详解
java·算法·c#
CodeByV6 小时前
【算法题】堆
算法