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小的元素 [题解] 我们对答 ...
随机推荐
- Android Dalvik虚拟机初识
摘自:http://blog.csdn.net/andyxm/article/details/6126907 首先,让我们来思考下面几个问题: 什么是Dalvik虚拟机? Dalvik VM与JVM有 ...
- golang安装开发环境配置
本机系统:fedora28 step 1 百度搜索 golang 到 go 语言中文网,下载 golang 包,如果是 linux 系统可以直接点击此连接,也可去 go 语言中文网, https:// ...
- Netty源码分析第2章(NioEventLoop)---->第8节: 执行任务队列
Netty源码分析第二章: NioEventLoop 第八节: 执行任务队列 继续回到NioEventLoop的run()方法: protected void run() { for (;;) ...
- WebRtc与SIP
最近研究一下 webrtc ,看了几篇paper,之前也尝试运行验证了几个demo,现在把我的理解总结到这里. WebRTC 简介 WebRTC,名称源自网页实时通信(Web Real-Time Co ...
- SSH 报错解决方法记录汇总
SSH 密钥签名失败 情景: 使用 SSH 密钥验证身份时 报错: sign_and_send_pubkey: signing failed: agent refused operation 环境: ...
- Django_rest_framework_组件(authentication、permission、throttle)
认证组件 说明 from rest_framework.authentication import BaseAuthentication class TestAuthentication(BaseAu ...
- MyForm_参考django的Form组建
fork wupeiqi:https://github.com/fat39/Tyrion 组件说明:https://www.cnblogs.com/wupeiqi/p/5938916.html
- model类的构造部分属性的对象 产生的json
在 action方法里, 产生一个对象,可能会是默认的全属性对象,那么在输出的 json就又所有 都出现了. 只是其他的属性全部是 null 那么 在 json里面配上 <!-- json 不产 ...
- 经验分享(Android开发)
以前对于Android开发一点了解都没有,当然,以前觉得是一件很高大上的事情,而且是我没有能力去做的工作,但是在这个小组合作开发Android后,我觉得我有了很大的进步,当然我的进步也是Android ...
- Week2-作业1
第一章:引用:如果一架民用飞机上有一个功能,用户使用它的概率是百万分之一,你还要做这个功能么? 选择之后,这个功能是什么呢?谜底是飞机的安全功能. 个人认为,飞机的安全功能这个 ...