bzoj4165 矩阵 堆维护多路归并
题目传送门
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; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 上周热点回顾(1.20-1.26)
2018-10-28 HEOI2015 兔子与樱花
2018-10-28 ZJOI2006 三色二叉树
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)C-洞穴
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)B-随机生成树
2018-10-28 牛客网NOIP赛前集训营-提高组(第七场)A-中国式家长 2