题目描述

给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。

输入

 
第一行两个数N,Q,表示矩阵大小和询问组数;
接下来N行N列一共N*N个数,表示这个矩阵;
再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。

输出

对于每组询问输出第K小的数。

样例输入

2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3

样例输出

1
3

提示

矩阵中数字是109以内的非负整数;
20%的数据:N<=100,Q<=1000;
40%的数据:N<=300,Q<=10000;
60%的数据:N<=400,Q<=30000;
100%的数据:N<=500,Q<=60000。

考虑暴力,对于每次询问二分答案,求权值$\le mid$的点的个数是否有$k$个,显然时间复杂度爆炸。

我们将所有询问一起二分,也就是整体二分。

先将每个点的权值排序,每次将权值$\le mid$的点加入到矩阵中,然后对当前要处理的所有询问进行查询。

如果查询矩形内点个数大于等于$k$那么说明这个询问的答案要在$[l,mid]$中,就将这个询问归为左区间,否则将询问的$k$减掉这次查询的结果,归为右区间。这样递归下去即可得到每个询问的答案。

至于查询矩形内点数用二维树状数组差分一下即可。

每层处理完不要忘记把树状数组清空。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int v[510][510];
struct lty
{
int x,y,val;
}a[250010];
int cnt;
int num;
struct miku
{
int a,b,c,d,k;
}q[60010];
int ans[60010];
int s[60010];
int ql[60010];
int qr[60010];
bool cmp(lty a,lty b)
{
return a.val<b.val;
}
void add(int x,int y,int val)
{
for(int i=x;i<=n;i+=i&-i)
{
for(int j=y;j<=n;j+=j&-j)
{
v[i][j]+=val;
}
}
}
int ask(int x,int y)
{
int res=0;
for(int i=x;i;i-=i&-i)
{
for(int j=y;j;j-=j&-j)
{
res+=v[i][j];
}
}
return res;
}
int query(int a,int b,int c,int d)
{
return ask(c,d)-ask(c,b-1)-ask(a-1,d)+ask(a-1,b-1);
}
void solve(int l,int r,int L,int R)
{
if(L>R)
{
return ;
}
if(l==r)
{
for(int i=L;i<=R;i++)
{
ans[s[i]]=a[l].val;
}
return ;
}
int mid=(l+r)>>1;
for(int i=l;i<=mid;i++)
{
add(a[i].x,a[i].y,1);
}
int sl=L,sr=R;
for(int i=L;i<=R;i++)
{
int res=query(q[s[i]].a,q[s[i]].b,q[s[i]].c,q[s[i]].d);
if(res>=q[s[i]].k)
{
ql[sl++]=s[i];
}
else
{
qr[sr--]=s[i];
q[s[i]].k-=res;
}
}
for(int i=L;i<sl;i++)
{
s[i]=ql[i];
}
for(int i=sr+1;i<=R;i++)
{
s[i]=qr[i];
}
for(int i=l;i<=mid;i++)
{
add(a[i].x,a[i].y,-1);
}
solve(l,mid,L,sl-1),solve(mid+1,r,sr+1,R);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
num++;
scanf("%d",&a[num].val);
a[num].x=i,a[num].y=j;
}
}
sort(a+1,a+1+num,cmp);
for(int i=1;i<=m;i++)
{
cnt++;
scanf("%d%d%d%d%d",&q[cnt].a,&q[cnt].b,&q[cnt].c,&q[cnt].d,&q[cnt].k);
s[i]=i;
}
solve(1,num,1,cnt);
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
}

BZOJ2738矩阵乘法——整体二分+二维树状数组的更多相关文章

  1. [BZOJ2738]矩阵乘法 整体二分+二维树状数组

    2738: 矩阵乘法 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1643  Solved: 715[Submit][Status][Discuss ...

  2. 【bzoj2738】矩阵乘法 整体二分+二维树状数组

    题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入 第一行两个数N,Q,表示矩阵大小和询问组数:接下来N行N列一共N*N个数,表示这个矩阵:再接下来Q行每行5个数 ...

  3. BZOJ.2738.矩阵乘法(整体二分 二维树状数组)

    题目链接 BZOJ 洛谷 整体二分.把求序列第K小的树状数组改成二维树状数组就行了. 初始答案区间有点大,离散化一下. 因为这题是一开始给点,之后询问,so可以先处理该区间值在l~mid的修改,再处理 ...

  4. [BZOJ2738]矩阵乘法(整体二分+二维树状数组)

    整体二分+二维树状数组. 好题啊!写了一个来小时. 一看这道题,主席树不会搞,只能用离线的做法了. 整体二分真是个好东西,啥都可以搞,尤其是区间第 \(k\) 大这种东西. 我们二分答案,然后用二维树 ...

  5. BZOJ 2738 矩阵乘法(整体二分+二维树状数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答 ...

  6. 【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)

    试题来源 2012中国国家集训队命题答辩 问题描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入格式 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共 ...

  7. 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...

  8. 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]

    题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...

  9. 洛谷P1527 矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...

随机推荐

  1. CSS Modules入门教程

    为什么引入CSS Modules 或者可以这么说,CSS Modules为我们解决了什么痛点.针对以往我写网页样式的经验,具体来说可以归纳为以下几点: 全局样式冲突 过程是这样的:你现在有两个模块,分 ...

  2. Jmeter实例(二)简单的性能测试场景

    我们在性能测试过程中,首先应该去设计测试场景,模拟真实业务发生的情境,然后针对这些场景去设计测试脚本.为了暴露出性能问题,要尽可能的去模拟被测对象可能存在瓶颈的测试场景. 我在本地部署了一个项目,可以 ...

  3. 容器互联(linking)

    容器互联(linking)是一种让多个容器中的应用进行快速交互的方式. 它会在源和接受容器中间创建连接关系,接受容器可以通过容器名快速访问到源容器而不用指出具体的IP地址.

  4. python二:数据类型举例练习--小白博客

    一.#字符串 res = 'hello,world' 1.#字符串切片取值:******* print(res[0:5]) 顾头不顾尾,取下标0-4的字符 print(res[0:-1:2]) 步长为 ...

  5. Pair Project

    以前只是一个人完成一个项目,不论什么都是,现在突然要两个人一起来写, 听上去挺稀奇的,也挺简单的,可惜了就是“听上去”而已.我认为这也是一种技术啊~ 我跟我的搭档研究了好久好久,选择了好久,然后也选了 ...

  6. Python之json使用

    一.概念 json是一种通用的数据类型,任何语言都认识 接口返回的数据类型都是json 长得像字典,形式也是k-v { } 其实json是字符串 字符串不能用key.value来取值,要先转成字典才可 ...

  7. vue组件内部引入远程js文件

    之所以要做这个是因为,在一个组件内部需要引入一个js文件来定位.如果放在index.html,这样每个组件都会有这个js.所以需要在组件内单独引入. 第一种操作 Dom引入js: export def ...

  8. PHPUnit实践一(初识)

    PHPUnit实践一(初识)     本系列教程所有的PHPUnit测试基于PHPUnit6.5.9版本,Lumen 5.5框架 前置 日常我们的普通用到的测试: 代码直接echo,debug等方法测 ...

  9. 编写自己的composer项目

    编写自己的composer项目   composer的出现给php开发带来极大的便利, 配合phpunit的测试工具, 也可以更好的规范php开发. 尽管这些标准不是官方提供的, 但现在大部分的php ...

  10. 2 JAVA 项目名称前红色叹号如何解决

    1 Java 项目前出现红色叹号Eclipse找不到项目需要的JAR包,可以在这里面解决: ① 右键点击项目,选择[Build Path].[Configure Build Path...] ② 在这 ...