题意:给你一个n * m的矩阵,问所有的a * b的子矩阵的最小的元素的和是多少。题目给出了矩阵中的数的数据生成器。

思路:如果这个问题是1维的,即求所有区间的最小元素的和,用单调队列O(n)就可以做。对于这个问题,我们先给每一行建一个单调队列,枚举子矩阵的行坐标的左端点和右端点。在行的左右端点的基础上,用另一个单调队列维护子矩阵每一行的最小值。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pii pair<int, int>
#define LL long long
#define db double
using namespace std;
const int maxn = 3001;
pii q[maxn];
int l, r;
int q3[maxn][maxn], l3[maxn], r3[maxn];
int a[maxn][maxn];
int n, m;
void init(int p, int L, int R) {
for (int j = L; j <= R; j++) {
int tmp = a[p][j];
while(l3[p] <= r3[p] && a[p][q3[p][r3[p]]] >= tmp) r3[p]--;
q3[p][++r3[p]] = j;
}
}
void maintain(int p, int L, int R) {
int tmp = a[p][R];
while(l3[p] <= r3[p] && q3[p][l3[p]] < L) l3[p]++;
while(l3[p] <= r3[p] && a[p][q3[p][r3[p]]] >= tmp) r3[p]--;
q3[p][++r3[p]] = R;
}
int query(int p) {
return a[p][q3[p][l3[p]]];
}
int main() {
int a1, b1, now, x, y, z;
scanf("%d%d%d%d", &n, &m, &a1, &b1);
scanf("%d%d%d%d", &now, &x, &y, &z);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
a[i][j] = now;
now = ((LL)now * x + y) % z;
}
}
for (int i = 1; i <= n; i++) l3[i] = 1;
LL ans = 0;
for (int i = 1; i <= n; i++) {
init(i, 1, b1 - 1);
}
for (int l1 = 1, r1 = b1; r1 <= m; l1++, r1++) {
l = 1, r = 0;
for (int j = 1; j <= a1; j++) {
maintain(j, l1, r1);
int tmp = query(j);
while(l <= r && q[r].second >= tmp) r--;
q[++r] = make_pair(j, tmp);
}
ans += q[l].second;
for (int l2 = 2, r2 = a1 + 1; r2 <= n; l2++, r2++) {
while(l <= r && q[l].first < l2) l++;
maintain(r2, l1, r1);
int tmp = query(r2);
while(l <= r && q[r].second >= tmp) r--;
q[++r] = make_pair(r2, tmp);
ans += q[l].second;
}
}
printf("%lld\n", ans);
}

  

Codeforces 1195E OpenStreetMap 单调队列套单调队列的更多相关文章

  1. Codeforces - 1195E - OpenStreetMap - 单调队列

    https://codeforc.es/contest/1195/problem/E 一个能运行但是会T的版本,因为本质上还是\(O(nmab)\)的算法.每次\(O(ab)\)初始化矩阵中的可能有用 ...

  2. Codeforces 1195E. OpenStreetMap (单调队列)

    题意:给出一个n*m的矩形.询问矩形上所有的a*b的小矩形的最小值之和. 解法:我们先对每一行用单调栈维护c[i][j]代表从原数组的mp[i][j]到mp[i][j+b-1]的最小值(具体维护方法是 ...

  3. bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

    详见vfleaking在discuss里的题解. 收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过. 暴力 ...

  4. 【learning】 单调队列与单调栈用法详解

    1.单调栈 单调栈是指一个栈内部的元素具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈. 其具有以下两个性质: 1,满足栈底到栈顶的元素具有严格单调性. 2,满足栈的先进后出特性,越靠近栈顶的 ...

  5. 单调栈and单调队列(此文太多坑了,以后再填)

    单调栈 单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递减. 性质: 单调栈里的元素具有单调性 元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除 使用单调 ...

  6. 22.1.23Manacher算法、双端队列、单调栈

    22.1.23Manacher算法.双端队列.单调栈 1.Manacher算法 1)用途: Manacher算法用于解决类似求某个字符串中最长的回文子串.(回文就是正着读和倒着读一样的结构). 2)算 ...

  7. JAVA多线程(二) 并发队列和阻塞队列

    github代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service/ ...

  8. C ~ 链式队列与循环队列

          此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...

  9. C语言 复杂队列(链表队列)

    //复杂的队列二 --链表队列 #include<stdio.h> #include<stdlib.h> #define datatype int struct queueli ...

随机推荐

  1. [BZOJ2341][Shoi2011]双倍回文 manacher+std::set

    题目链接 发现双倍回文串一定是中心是#的回文串. 所以考虑枚举#点.发现以\(i\)为中心的双倍回文的左半部分是个回文串,其中心一定位于\(i-\frac{pal[i]-1}2\)到\(i-1\)之间 ...

  2. FreeBSD虚拟机——小折腾

    最近,突然想起来Linux了,因为前段时间接触了DOS命令,提高了自己的工作效率,这会想再温习下Linux的CLI,无奈windows下unix命令,水土不服,因此想尝试虚拟机,虚拟机软件无非vmwa ...

  3. Autoit3域用户的登陆统计

    #include <ACN_NET.au3> If @OSArch="X86" Then $fileURL=@CommonFilesDir & "\S ...

  4. 【leetcode】1021. Best Sightseeing Pair

    题目如下: Given an array A of positive integers, A[i]represents the value of the i-th sightseeing spot, ...

  5. CF1111C Creative Snap 线段树

    用线段树模拟一下就好了~ code: #include <cstdio> #include <algorithm> #define lson ls[x] #define rso ...

  6. Java IO流总结(二)-示例

    1.使用文件操作的9大方法完成文件的判断 判断文件或目录是否存在 : exits() 返回值boolean型 * 判断是否是文件: isFile() boolean * 判断是否是目录: isDiec ...

  7. VMware安装MAC OS

    测试环境 安装环境:win10 .VMware Workstation Pro14 镜像:OS X 10.11.5(由于太大,就没有上传网盘,网上也有很多资源) 安装准备 安装前先把关于VMware的 ...

  8. Gym-100676F Palindrome

    原题连接:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1491063604 题意: 多组输入,每一次输入一个n(字符串 ...

  9. char指针类型的传值和传址

  10. git add 添加错文件的撤销方法

    git add 添加 多余文件 这样的错误是由于,有的时候 可能 git add . (空格+ 点) 表示当前目录所有文件,不小心就会提交其他文件 git add 如果添加了错误的文件的话 撤销操作 ...