BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治
BZOJ 2738 “矩阵乘法”(子矩阵第k大)
题意
给出一个矩阵,多次询问子矩阵中第k大的数是多少。
题解
我做这道题之前先照着这道题出了一道题,是这道题的一维版本,在这里:https://vijos.org/d/contest/p/5a26541bd3d8a11cef1706aa。
思路是这样的:二分答案mid,将所有小于mid的位置都在树状数组上 +1,对于每个询问,如果子矩阵所有”+1“之和 >= 这个询问的k,则把询问划分到”左边那一组”,否则划分到“右边那一组”,之后对它们分别处理。
核心代码:
void solve(int l, int r, int ql, int qr){
if(ql > qr) return;
if(l == r){
for(int i = ql; i <= qr; i++)
ans[q[i].id] = a[l].val;
return;
}
int mid = (l + r) >> 1, cnt = 0;
for(int i = l; i <= mid; i++)
add(a[i].x, a[i].y, 1);
for(int i = ql; i <= qr; i++){
sum[i] = ask(q[i]);
if(sum[i] >= q[i].k) cnt++;
}
for(int i = ql, pl = ql, pr = ql + cnt; i <= qr; i++)
if(sum[i] >= q[i].k) tmp[pl++] = q[i];
else q[i].k -= sum[i], tmp[pr++] = q[i];
for(int i = ql; i <= qr; i++) q[i] = tmp[i];
for(int i = l; i <= mid; i++)
add(a[i].x, a[i].y, -1);
solve(l, mid, ql, ql + cnt - 1);
solve(mid + 1, r, ql + cnt, qr);
}
完整代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 505, M = 60005;
int n, m, tr[N][N], ans[M], idx, sum[M];
struct element {
int x, y, val;
bool operator < (const element &b) const{
return val < b.val;
}
} a[N*N];
struct query {
int id, xa, ya, xb, yb, k;
} q[M], tmp[M];
void add(int x, int y, int val){
for(int px = x; px <= n; px += px & -px)
for(int py = y; py <= n; py += py & -py)
tr[px][py] += val;
}
int single_ask(int x, int y){
int ret = 0;
for(int px = x; px; px -= px & -px)
for(int py = y; py; py -= py & -py)
ret += tr[px][py];
return ret;
}
int ask(query Q){
return single_ask(Q.xb, Q.yb) - single_ask(Q.xa - 1, Q.yb) - single_ask(Q.xb, Q.ya - 1) + single_ask(Q.xa - 1, Q.ya - 1);
}
void solve(int l, int r, int ql, int qr){
if(ql > qr) return;
if(l == r){
for(int i = ql; i <= qr; i++)
ans[q[i].id] = a[l].val;
return;
}
int mid = (l + r) >> 1, cnt = 0;
for(int i = l; i <= mid; i++)
add(a[i].x, a[i].y, 1);
for(int i = ql; i <= qr; i++){
sum[i] = ask(q[i]);
if(sum[i] >= q[i].k) cnt++;
}
for(int i = ql, pl = ql, pr = ql + cnt; i <= qr; i++)
if(sum[i] >= q[i].k) tmp[pl++] = q[i];
else q[i].k -= sum[i], tmp[pr++] = q[i];
for(int i = ql; i <= qr; i++) q[i] = tmp[i];
for(int i = l; i <= mid; i++)
add(a[i].x, a[i].y, -1);
solve(l, mid, ql, ql + cnt - 1);
solve(mid + 1, r, ql + cnt, qr);
}
int main(){
read(n), read(m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
a[++idx].x = i, a[idx].y = j, read(a[idx].val);
sort(a + 1, a + idx + 1);
for(int i = 1; i <= m; i++)
q[i].id = i, read(q[i].xa), read(q[i].ya), read(q[i].xb), read(q[i].yb), read(q[i].k);
solve(1, idx, 1, m);
for(int i = 1; i <= m; i++)
write(ans[i]), enter;
return 0;
}
BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治的更多相关文章
- 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...
- 洛谷P1527 矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...
- BZOJ 1452 Count 【模板】二维树状数组
对每种颜色开一个二维树状数组 #include<cstdio> #include<algorithm> using namespace std; ; ][maxn][maxn] ...
- 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)
BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...
- BZOJ 1452:[JSOI2009]Count(二维树状数组)
[JSOI2009]Count 描述 输入 输出 1 2 分析: 裸二维bit,对每个颜色建一颗bit. program count; var bit:..,..,..]of longint; a:. ...
- POJ 1195:Mobile phones 二维树状数组
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16893 Accepted: 7789 De ...
- BZOJ.2738.矩阵乘法(整体二分 二维树状数组)
题目链接 BZOJ 洛谷 整体二分.把求序列第K小的树状数组改成二维树状数组就行了. 初始答案区间有点大,离散化一下. 因为这题是一开始给点,之后询问,so可以先处理该区间值在l~mid的修改,再处理 ...
- BZOJ 2738 矩阵乘法(整体二分+二维树状数组)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答 ...
随机推荐
- 木马分析出现python语言,360的安全人员不禁感叹还有这种操作?
几年前,敲诈者木马还是一个默默无闻的木马种类.然而,由于其极强的破坏力和直接且丰厚的财富回报,敲诈者木马这几年已经一跃成为曝光率最高的木马类型——甚至超越了盗号木马.远控木马.网购木马这传统三强.与此 ...
- 【总结】Java面试题
部分转自 https://blog.csdn.net/junchi_/article/details/79754032 一.String特性.StringBuffer 和 StringBuilder ...
- 机器人平台框架Yarp - Yet another robot platform
简介 ROS有强大和易用的特性,用的人很多,目前已经推出2.0版本,有相关的官网和论坛.然而其缺点也比较明显. 只能基于Ubuntu系统,且一个ROS版本只能对应一个具体的Ubuntu版本 通信 ...
- [mysql] 归档工具pt-archiver,binlog格式由mixed变成row
pt-archiver官方地址:https://www.percona.com/doc/percona-toolkit/3.0/pt-archiver.html 介绍:归档数据,比如将一年前的数据备份 ...
- RN 离线包集成后需要注意的一些问题
1.ReactNative 开发中如何去掉iOS状态栏的"Loading from..." 等淡黑色的弹框,很难看? 在 AppDelegate.h 中引入: #import &l ...
- No.1001_第六次团队会议
黯淡的一日 今天发生了很令人不爽的一件事,杜正远又被叫去实验室了.昨天界面就很难做,而且我们组人手稀缺,他的缺席让我很难做下去. 今天开会我自己没做出什么来,就加了一个群组的添加功能,同样,曾哲昊也没 ...
- 奔跑吧DKY——团队Scrum冲刺阶段-Day 6
今日完成任务 谭鑫:制作相应动画人物,并实现人物动画 黄宇塘:制作相应动画人物,并实现人物动画,制作背景图 赵晓海:制作相应动画人物,并实现人物动画 方艺雯:制作相应动画人物,并实现人物动画,编写博客 ...
- 第一周冲刺评论总结&&针对评论总结的改进
关于功能:1.统计功能需完善,提高产品功能,突出功能重点,使功能完善. 2.希望增加功能. 3.该产品能查看单个同学的博客,但按要求查询时只能查找最后一次发布的博客,且未进行信息的合理分类,望之后能多 ...
- 如何获取启动页activity
启动页activity指App启动的第一个activity,介绍几种查看启动页activity的方法: 方法一:问开发,最有效的获取方式 方法二:dumpsys package 包名,前提是知道包名( ...
- 关于mybatis的思考(1)——mybatis的使用实例
架构分析 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架. MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索.MyBatis 可以使用简 ...