题目传送门

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. webpack前置知识1(模块化开发)

    webpack前置知识1(模块化开发) 新建 模板 小书匠  在开始对模块化开发进行讲解之前,我们需要有这么一个认识,即 在没有过多第三方干扰时,成本低收益高的事物更容易获得推广和信赖. 模块化开发就 ...

  2. LInux 下PHP环境配置 Redis 总结

    系统 Deepin ,环境 PHP7.0 + Apache2 安装 Redis 服务 sudo apt-get install redis-server //安装 sudo /etc/init.d/r ...

  3. 复选框checked 选中后不显示打钩

    复选框checked 选中后不显示打钩 checkbox属性checked="checked"已有,但复选框却不显示打钩的原因   复选框绑定了click事件,点一次选中,再点击取 ...

  4. PLSQL导出还原数据库

    1  导出存储过程,触发器,序列等所有用户对象.(备份) 导出所有的表,存储过程,触发器,序列等所有的创建语句(.sql文件) 在PL/SQL Developer的菜单Tools(工具) => ...

  5. python - property 属性函数

    Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情.在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter ...

  6. Selenium学习之==>三种等待方式

    在UI自动化测试中,必然会遇到环境不稳定,网络慢的情况,这时如果你不做任何处理的话,代码会由于没有找到元素,而报错.这时我们就要用到wait(等待),而在Selenium中,我们可以用到一共三种等待, ...

  7. map根据属性排序、取出map前n个

    /** * map根据value排序 * flag = 1 正序 * flag = 0 倒序 * * @param map * @param flag * @return */ public stat ...

  8. 【算法与数据结构】二叉堆和优先队列 Priority Queue

    优先队列的特点 普通队列遵守先进先出(FIFO)的规则,而优先队列虽然也叫队列,规则有所不同: 最大优先队列:优先级最高的元素先出队 最小优先队列:优先级最低的元素先出队 优先队列可以用下面几种数据结 ...

  9. 【SD系列】SAP SD凭证处理被批次处理冻结

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[SD系列]SAP SD凭证处理被批次处理冻结 ...

  10. 【LeetCode】121、买卖股票的最佳时机

    Best Time to Buy and Sell Stock 题目等级:Easy 题目描述: Say you have an array for which the ith element is t ...