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小的元素 [题解] 我们对答 ...
随机推荐
- 在CentOS7上部署PostgreSQL11数据库系统
在数据库上的选择,也是基于了稳定性为前提.其实选择的范围并不是太大,基本可以选择的范围也就是SQLServer.MySQL.PostgreSQL这三种.SQL Server是微软的商业数据库,无论是性 ...
- appium+python+unittest 测试用例的几种加载执行方式
利用python进行测试时,测试用例的加载方式有2种: 一种是通过unittest.main()来启动所需测试的测试模块: 一种是添加到testsuite集合中再加载所有的被测试对象,而testsu ...
- GearCase UI - 自己构建一套基于 Vue 的简易开源组件库
最近 1 ~ 2 月除了开发小程序之外,还一直在继续深入的学习 Vuejs.利用零碎.闲暇的时间整合了一套基于 Vue 的 UI 组件库.命名为 GearCase UI,意为齿轮盒.现在把该项目进行开 ...
- Hyperledger Fabric CA User’s Guide——开始(三)
Fabric CA User’s Guide——开始 先决条件 安装Go 1.9+ 设置正确的GOPATH环境变量 安装了libtool和libtdhl-dev包 下面是在Ubuntu上安装libto ...
- [T-ARA][느낌 아니까][懂得那份感觉]
歌词来源:http://music.163.com/#/song?id=27808771 作曲 : 박덕상/박현중 [作曲 : p/bag-ddeog-ssang-/p/ba-Kyeon-c/jung ...
- Final冲刺贡献分
小组名称:Hello World! 项目名称:空天猎 组长:陈建宇 成员:刘成志.刘耀泽.刘淑霞.黄泽宇.方铭.贾男男 一.贡献分数规则: (1)基础分:5 , 4 ,4 , 3 , 2 ,2 ,1. ...
- 20172325 2016-2017-2 《Java程序设计》第四周学习总结
20172325 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 1.对类.对象.声明变量的定义和属性有了进一步的了解 2.学会如何编写一个类并运用到需要的程 ...
- pycharm 2017注册码
1.在浏览器的地址栏输入:http://idea.lanyus.com/,该网址,无需修改用户名,点击获取注册码.复制该注册码,粘贴在注册界面的Activation code的输入框中,点击 ok 该 ...
- Error: Unable to access jarfile D:\Apache\apache-jmeter-3.0\bin\ApacheJMete.jar
双击jmeter.bat后,在cmd窗口显示Error: Unable to access jarfile D:\Apache\apache-jmeter-3.0\bin\ApacheJMete.ja ...
- [转帖]HTTPS的简单说明
HTTPS(全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTT ...