【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)
接下来N行N列一共N*N个数,表示这个矩阵;
再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
2 1
3 4
1 2 1 2 1
1 1 2 2 3
3
20%的数据:N<=100,Q<=1000;
40%的数据:N<=300,Q<=10000;
60%的数据:N<=400,Q<=30000;
100%的数据:N<=500,Q<=60000。
/*
李商隐
《无题·重帏深下莫愁堂》
重帏深下莫愁堂,卧后清宵细细长。
神女生涯原是梦,小姑居处本无郎。
风波不信菱枝弱,月露谁教桂叶香。
直道相思了无益,未妨惆怅是清狂。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#define LOCAL
const int MAXN = + ;
const int MAXM = + ;
const int INF = ;
const int SIZE = ;
const int maxnode = + ;
using namespace std;
typedef long long ll;
using namespace std;
int n, m, cnt;
int pos, Maxv;
int c[MAXN][MAXN], Ans[MAXM];
int id[MAXM];
int tmp[MAXM];
bool mark[MAXM]; struct DATA{
//横纵坐标和值
int x, y, val;
bool operator < (const DATA &b)const {
return val < b.val;
}
}data[maxnode];
//问题
struct QUESTION{
int x1, x2;
int y1, y2, K;
}q[MAXM];
//输入 inline int lowbit(int x){return x & -x;}
//插入
void add(int x, int y, int val){
int f = y;
while (x <= n){
while (y <= n){
c[x][y] += val;
y += lowbit(y);
}
y = f;
x += lowbit(x);
}
return;
}
int sum(int x, int y){//和
int tmp = , f = y;
while (x > ){
while (y > ){
tmp += c[x][y];
y -= lowbit(y);
}
y = f;
x -= lowbit(x);
}
return tmp;
}
//查询
int query(int k){
int x1, x2, y1, y2;
x1 = q[k].x1;x2 = q[k].x2;
y1 = q[k].y1;y2 = q[k].y2;
return sum(x2, y2) + sum(x1 - , y1 - ) - sum(x1 - , y2) - sum(x2, y1 - );
}
//整体二分
void solve(int l, int r, int L, int R){
if (l > r || L == R) return;//l和r是问题的编号
int mid = (L + R) >> ; while (data[pos + ].val <= mid && pos < cnt){//直接模拟
add(data[pos + ].x, data[pos + ].y, );
pos++;
}
while (data[pos].val > mid){
add(data[pos].x, data[pos].y , -);
pos--;
}
int cnt = ;
for (int i = l; i <= r; i++){
if (query(id[i]) > q[id[i]].K - ){
mark[i] = ;
Ans[id[i]] = mid;
cnt++;
}else mark[i] = ;
}
int l1 = l, l2 = l + cnt;
for (int i = l; i <= r; i++)
if (mark[i]) tmp[l1++] = id[i];
else tmp[l2++] = id[i];
//分成两部分继续整体二分
for (int i = l; i <= r; i++) id[i] = tmp[i];
solve(l, l1 - , L, mid);
solve(l1, l2 - , mid + , R);
} void init(){
memset(mark, , sizeof(mark));
memset(c, , sizeof(c));
scanf("%d%d", &n, &m);
Maxv = ;
cnt = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++){
scanf("%d", &data[++cnt].val);
data[cnt].x = i;//横纵坐标
data[cnt].y = j;
Maxv = max(data[cnt].val, Maxv);
}
sort(data + , data + + cnt);
}
void work(){
for (int i = ; i <= m; i++){
scanf("%d%d%d%d%d", &q[i].x1, &q[i].y1, &q[i].x2, &q[i].y2, &q[i].K);
}
for (int i = ; i <= m; i++) id[i] = i;//问题序列
solve(, m, , Maxv + );
for (int i = ; i <= m; i++) printf("%d\n", Ans[i]);
} int main(){ init();
work();
return ;
}
【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)的更多相关文章
- [BZOJ2738]矩阵乘法(整体二分+二维树状数组)
整体二分+二维树状数组. 好题啊!写了一个来小时. 一看这道题,主席树不会搞,只能用离线的做法了. 整体二分真是个好东西,啥都可以搞,尤其是区间第 \(k\) 大这种东西. 我们二分答案,然后用二维树 ...
- 【bzoj2738】矩阵乘法 整体二分+二维树状数组
题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入 第一行两个数N,Q,表示矩阵大小和询问组数:接下来N行N列一共N*N个数,表示这个矩阵:再接下来Q行每行5个数 ...
- BZOJ2738矩阵乘法——整体二分+二维树状数组
题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入 第一行两个数N,Q,表示矩阵大小和询问组数:接下来N行N列一共N*N个数,表示这个矩阵:再接下来Q行每行5 ...
- BZOJ.2738.矩阵乘法(整体二分 二维树状数组)
题目链接 BZOJ 洛谷 整体二分.把求序列第K小的树状数组改成二维树状数组就行了. 初始答案区间有点大,离散化一下. 因为这题是一开始给点,之后询问,so可以先处理该区间值在l~mid的修改,再处理 ...
- BZOJ 2738 矩阵乘法(整体二分+二维树状数组)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答 ...
- [BZOJ2738]矩阵乘法 整体二分+二维树状数组
2738: 矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1643 Solved: 715[Submit][Status][Discuss ...
- 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]
题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...
- 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...
- 洛谷P1527 矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...
随机推荐
- Linux学习笔记19——信号2
上一节中讲到了sigprocmask函数,它的作用是检查或修改它的进程信号掩码,这一节我们主要学习捕捉与忽略信号的函数sigaction和等待信号函数. 一 sigaction函数的作用 定义在接收 ...
- JVM性能调优-GC内存模型及垃圾收集算法
JVM内存管理模型: http://developer.51cto.com/art/201002/184385.htm 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在 ...
- Ural 1332 把圆细分+圆内切,内含关系判定
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1332 #include<cstdio> #include<cstrin ...
- Java 内存泄露的理解与解决过程
本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对各位Java开发者有所帮助. Java内存管理机制 在C++ 语言中,如果需要动态分配 ...
- Struct2 向Action中传递参数(中文乱码问题)
就是把视图上的值传递到Action定义的方法中 也就是把数据从前台传递到后台 三种方式: 1. 使用action属性接收参数 比如jsp页面: <body> 使用action属性接收参数 ...
- 索引查找(索引查找、分块查找) C语言实现
1.基本概念 索引查找又称分级查找. 索引存储的基本思想是:首先把一个集合或线性表(他们对应为主表)按照一定的函数关系或条件划分成若干个逻辑上的子表,为每个子表分别建立一个索引项,由所有 这些索引项构 ...
- UVA 753 - A Plug for UNIX(网络流)
A Plug for UNIX You are in charge of setting up the press room for the inaugural meeting of the U ...
- Android中Style和Theme的使用
Style: Style是View中一些属性的集合,包括height,padding,font color,background等等,Style单独定义在xml文件中,类似与web页面中css的角色, ...
- Android自定义drawable(Shape)详解
在Android开发过程中,经常需要改变控件的默认样式, 那么通常会使用多个图片来解决.不过这种方式可能需要多个图片,比如一个按钮,需要点击时的式样图片,默认的式样图片. 这样就容易使apk变大. 那 ...
- php判断http头还是https头
$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HT ...