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小的元素 [题解] 我们对答 ...
随机推荐
- Caffe Blob针对图像数据在内存中的组织方式
Caffe使用Blob结构在CNN网络中存储.传递数据.对于批量2D图像数据,Blob的维度为 图像数量N × 通道数C × 图像高度H × 图像宽度W 显然,在此种场景下,Blob使用4维坐标定位数 ...
- Android Library开发注意事项
Android Library开发注意事项 App Module添加依赖Android Library时可以设置library的优先级, 在编译时,app按照library从低到高的优先级依次与每个l ...
- 利用saltstack一键部署多台zookeeper
以上是saltstack上面sls文件存放zookeeper的路径和文件 以上是入口文件把文件夹做成包 重要安装配置在zoo.sls,以下是该sls的内容 zookeeper: file.manage ...
- go 运行项目
此时运行项目,不能像之前简单的使用go run main.go,因为包main包含main.go和router.go的文件,因此需要运行go run *.go命令编译运行.如果是最终编译二进制项目,则 ...
- SQL ser 进行表中的插入操作时,变量字段名,导致报错时解决办法 :动态SQL
标题不能描述的很清楚,下面具体说所我要描述的问题,和解决的办法. 作为SQL小白一枚,近日在写一段代码,代码如下: 报错显示 变量@vv附近错误. 后来经过了解,原来是因为,这样需要使用 动态SQL去 ...
- nginx keepalived 高可用方案(转)
转自: https://www.cnblogs.com/leeSmall/p/9356535.html 一.Nginx Rewrite 规则 1. Nginx rewrite规则 Rewrite规则含 ...
- Beta周王者荣耀交流协会第五次Scrum会议
1. 立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:王磊 2. 时间跨度 2017年11月14日 19:00 — 19:50 ,总计50分钟. 3. 地点 一食 ...
- 第38次Scrum会议(12/4)【欢迎来怼】
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/12/4 17:50~18:20,总计30min. 地点 ...
- spring冲刺第一天
第一天总结 昨天我们开始了spring冲刺会议,我们进行了明确的分工,每个人都有自己的任务.我的目前任务是游戏地图的初步设计. 今天早上我们开了站立会议,算是正式开始了spring冲刺.我上网查找了一 ...
- 【Coursera】因子分析模型
一.协方差矩阵 协方差矩阵为对称矩阵. 在高斯分布中,方差越大,数据分布越分散,方差越小发,数据分布越集中. 在协方差矩阵中,假设矩阵为二维,若第二维的方差大于第一维的方差,则在图像上的体现就是:高斯 ...