题目传送门

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. MySQL技术内幕 InnoDB存储引擎 之 InnoDB体系架构

    后台线程 1.Master Thread 2.IO Thread 3.Purge Thread 4.Page Cleaner Thread  内存 重做日志在以下三种情况下将重做日志缓存中的内容刷新到 ...

  2. 杂项-PIN:百科

    ylbtech-杂项-PIN:百科 个人身份识别码(英语:Personal identification number,缩写为 PIN),又译为用户个人识别号码,常被称为PIN码(PIN number ...

  3. OpenCV在ARM-linux上的移植过程遇到的问题3---共享库中嵌套库居然带路径【未解决】

    [Linux开发]OpenCV在ARM-linux上的移植过程遇到的问题3-共享库中嵌套库居然带路径[未解决] 标签(空格分隔): [Linux开发] 移植opencv到tq2440 一.下载open ...

  4. Git 创建分支并合并主分支

    首先,我们创建dev分支,然后切换到dev分支: $ git checkout -b dev(等价于 $ git branch dev $ git checkout dev ) Switched to ...

  5. 20191118 Spring Boot官方文档学习(4.8)

    4.8. RSocket RSocket参考 RSocket是用于字节流传输的二进制协议.它通过单个连接传递的异步消息来启用对称交互模型. Spring框架的spring-messaging模块在客户 ...

  6. MAC_BOOKPRO苹果电脑系统常用快捷键大全

    Mac 键盘快捷键 我在品多多上拼的Mac终于到货了,安全下车,接下来要熟练使用了! 您可以按下某些组合键来实现通常需要鼠标.触控板或其他输入设备才能完成的操作.   要使用键盘快捷键,请按住一个或多 ...

  7. Java——HashMap使用Demo

    package map; import java.util.Collection; import java.util.HashMap; import java.util.Set; public cla ...

  8. webpack打包错误 ERROR in multi ./src/main.js ./dist/bundle.js

    webpack打包错误 ERROR in multi ./src/main.js ./dist/bundle.js:https://www.jianshu.com/p/a55fb5bf75e1

  9. P2010回文日期

    这道题是2016年普及组的题,难度等级为普及-. 这道题仍然是个模拟题.有两种策略:1.枚举回文,看日期是否存在2.枚举日期,看是否是回文.显然,前者要快很多,并且准确.本蒟蒻第一次便使用了后者,bu ...

  10. linux中断处理上下部分

    一.linux中断处理为什么要分为上下部 1.1. 中断处理的上半部(top half,又叫顶半部)和处理的下半部(bottom half,又叫底半部) 1.1. linux中断处理不参与调度,故中断 ...