题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=4165

题解

大概多路归并是最很重要的知识点了吧,近几年考察也挺多的(虽然都是作为签到题的)。

看到题目要求第 \(K\) 小矩阵,基本上可以想到用堆维护的 \(K\) 路归并。

然后我们考虑每一路是以 \((x_2, y_2)\) 为右下角的矩形的权值。那么初始的矩形的左上角应该是 \((x_2 - Mina, y_2 - Minb)\)。

于是我们用一个堆来维护这样的每一路。扩展每一路的话,因为把矩形的左边界或者上边界扩展一个单位以后权值肯定单调升,所以可以直接扩展一下左边界和上边界这两个矩形。但是这样可能会有重复的,所以拿一个 map 来判重一下。


这样的时间复杂度是 \(O(k\log nm)\)。

#include<bits/stdc++.h>
#include<tr1/unordered_set> #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 1000 + 7; int n, m, mina, minb, k;
int a[N][N];
ll s[N][N]; inline ll gsum(int x1, int y1, int x2, int y2) { return s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]; } struct Matrix {
int x1, y1, x2, y2;
inline Matrix() {}
inline Matrix(const int &x1, const int &y1, const int &x2, const int &y2) : x1(x1), y1(y1), x2(x2), y2(y2) {}
inline bool operator < (const Matrix &b) const { return gsum(x1, y1, x2, y2) > gsum(b.x1, b.y1, b.x2, b.y2); }
};
std::priority_queue<Matrix> q; std::tr1::unordered_set<ll> mp;
inline void set_mp(int x1, int y1, int x2, int y2) {
ll v = (((((ll)x1 * m) + y1) * n + x2) * m + y2);
mp.insert(v);
}
inline bool get_mp(int x1, int y1, int x2, int y2) {
ll v = (((((ll)x1 * m) + y1) * n + x2) * m + y2);
return mp.count(v);
} inline void work() {
for (int i = mina; i <= n; ++i)
for (int j = minb; j <= m; ++j) q.push(Matrix(i - mina + 1, j - minb + 1, i, j)), set_mp(i - mina + 1, j - minb + 1, i, j);
while (k--) {
Matrix t = q.top();
q.pop();
if (!k) return (void)printf("%lld\n", gsum(t.x1, t.y1, t.x2, t.y2));
if(t.x1 > 1 && !get_mp(t.x1 - 1, t.y1, t.x2, t.y2)) set_mp(t.x1 - 1, t.y1, t.x2, t.y2), q.push(Matrix(t.x1 - 1, t.y1, t.x2, t.y2));
if(t.y1 > 1 && !get_mp(t.x1, t.y1 - 1, t.x2, t.y2)) set_mp(t.x1, t.y1 - 1, t.x2, t.y2), q.push(Matrix(t.x1, t.y1 - 1, t.x2, t.y2));
}
} inline void init() {
read(n), read(m), read(mina), read(minb), read(k);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) read(a[i][j]), s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj4165 矩阵 堆维护多路归并的更多相关文章

  1. bzoj4165: 矩阵(堆+hash)

    求第k大用堆维护最值并出堆的时候扩展的经典题... 因为只有正数,所以一个矩阵的权值肯定比它的任意子矩阵的权值大,那么一开始把所有满足条件的最小矩阵加进堆里,弹出的时候上下左右扩展一行加进堆,用has ...

  2. 【bzoj4165】矩阵 堆+STL-map

    题目描述 定义和谐矩阵为长不小于 Mina 且宽不小于 Minb 的矩阵,矩阵的权值为整个矩阵内所有数的和.给定一个长为 N,宽为 M 的矩阵 A,求它的所有和谐子矩阵中权值第 K 小的矩阵,并输出它 ...

  3. UVA 11997 K Smallest Sums (多路归并)

    从包含k个整数的k个数组中各选一个求和,在所有的和中选最小的k个值. 思路是多路归并,对于两个长度为k的有序表按一定顺序选两个数字组成和,(B表已经有序)会形成n个有序表 A1+B1<=A1+B ...

  4. bzoj4165: 矩阵

    Description 定义和谐矩阵为长不小于 Mina 且宽不小于 Minb 的矩阵,矩阵的权值为整个矩阵内所有数的和.给定一个长为 N ,宽为 M 的矩阵 A,求它的所有和谐子矩阵中权值第 K 小 ...

  5. UVA11997求前k个和,多路归并问题

    题意:      给你一个二维矩阵,n*n的,每次从每一行中拿出来一个,然后加起来组成一个和,一共可以得到n^n个和,要求求出这n^n个和中最小的那n个和. 思路:      多路归并问题,先说下多路 ...

  6. uva 11997 K Smallest Sums 优先队列处理多路归并问题

    题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...

  7. [UOJ#268]. 【清华集训2016】数据交互[动态dp+可删堆维护最长链]

    题意 给出 \(n\) 个点的树,每个时刻可能出现一条路径 \(A_i\) 或者之前出现的某条路径 \(A_i\) 消失,每条路径有一个权值,求出在每个时刻过后能够找到的权值最大的路径(指所有和该路径 ...

  8. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  9. POJ 2010 Moo University - Financial Aid(堆维护滑窗kth,二分)

    按照score排序,贪心,从左到右用堆维护并且记录前面的最小N/2个花费之和. 然后从右向左枚举中位数,维护N/2个数之和加上并判断是否满足条件.(stl的队列没有clear(),只能一个一个pop. ...

随机推荐

  1. 前端Node项目发布流程

    最近在做前端的发布流程,发布流程的主要实现以下几个方面: 构建:包括JavaScript.css.html等的压缩,以及版本控制,利用md5生成版本号替换文件引用,实现长缓存策略. 发布:输出新版本的 ...

  2. 十五、RF操作时间控件

    由于日期控件经常用的是readonly属性,这个属性意思是此控件为可读,明白点就是只让你看,不让你动. 解决方法就是:用js去掉这个属性,就可写了,就能输入了 导入库:DateTime #方式一 op ...

  3. Linux_NetworkManager_RHEL7

    目录 目录 前言 网卡命名 RHEL7 的网卡命名规则 在RHEL7中修改回RHEL6的网卡命名规则方法 RHEL7的Network管理工具nmcli指令 nmcli指令 设置主机名 临时修改Host ...

  4. 数据库之SQL语句查询基础

    人的一生要疯狂一次,无论是为一个人,一段情,一段旅途,或一个梦想. 人没有梦想是荒废的,是漫无目的的,拥有梦想你会飞的更远. 下面我就来为大家介绍一下SQL语句的查询基础,以下使用MySchool数据 ...

  5. 使用事件CreateEvent注意事项 多进程同步的方法

    https://www.cnblogs.com/aakuang/p/3514658.html 使用事件CreateEvent注意事项   HANDLECreateEvent( LPSECURITY_A ...

  6. visualSVN提交强制添加注释

    Visual SVN Server下 右键项目  “所有任务”>“Manage Hooks” >选中Pre-commit hook然后edit编辑,添加如下代码 @echo off set ...

  7. python3--udp/TCP笔记和实践

    UDP协议: UDP (User Datagram Protocol, 用户数据报协议) 是一种无连接,不可靠,基于数据的传输层通信协议. UDP的通信过程与TCP相比比较为简单, 不需要复杂的三次握 ...

  8. 修改了Ubuntu下的/usr目录权限,导致不能使用sudo命令的修复-----转载

    刚开始运行sudo时,报了下面这个错误 sudo: must be setuid root,于是上网找解决方法,搜索出来的都是这样解决的 ls -l  /usr/bin/sudochown root: ...

  9. 爬取LeetCode题目——如何发送GraphQL Query获取数据

    前言   GraphQL 是一种用于 API 的查询语言,是由 Facebook 开源的一种用于提供数据查询服务的抽象框架.在服务端 API 开发中,很多时候定义一个接口返回的数据相对固定,因此要获得 ...

  10. 004 gcc 编译 C/C++ 默认使用哪个标准

    0. 前言 我挺久没碰 C,不想就这么忘了,最近重温了一些相关知识 1. C 语言的几种"方言" 简单地说,有这么几种常见的 年份 名称 1983 ANSI C 1987 C87 ...