题目描述

给你一个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. Maven项目pom.xml文件简单解析

    Maven项目pom.xml简单解析 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...

  2. mybatis源码-原来resultMap解析完是这样

    目录 1 两个基础类 1.1 列映射类ResultMapping 1.2 结果集映射类ResultMap 2. 解析 2.1 入口函数 2.2 解析流程 2.3 获取 id 2.4 解析结果集的类型 ...

  3. Kafka 入门三问

    目录 1 Kafka 是什么? 1.1 背景 1.2 定位 1.3 产生的原因 1.4 Kafka 有哪些特征 消息和批次 模式 主题和分区 生产者和消费者 broker 和 集群 1.5 Kafka ...

  4. git仓库迁移

    最近,装了git的本地服务器坏掉了, 没办法只能临时进行仓库的迁移  保证项目正常进行 在项目的根目录执行右键执行 查询当前仓库的远程地址 git remote -v 查看现有远程仓库的地址url 修 ...

  5. Charles 抓包工具安装和采坑记录

    Charles 抓包工具安装和采坑记录 网络抓包是解决网络问题的第一步,也是网络分析的基础.网络出现问题,第一步肯定是通过抓包工具进行路径分析,看哪一步出现异常.做网络爬虫,第一步就是通过抓包工具对目 ...

  6. python 打包下载 zipfile & tarfile

    看百度网盘我们会发现这么一个需求,新建一个文件夹,然后向文件夹中上传文件,点击文件夹可以直接下载,下载的是一个压缩文件,将文件夹中所有文件全部打包了下载下来. 在python中,我们要做文件打包下载, ...

  7. awk分析mysql状态

    今天是腊月27,明天是腊月28,一到过年,就习惯说农历,而不说公历.这两天挺闲的,就再造一把. 话说Linux处理文本工具有三剑客,awk.grep.sed,其中awk最为厉害,grep也挺是常用.今 ...

  8. C++常用代码优化策略

    C++代码常用的优化策略 1.不存在指向空值的引用,意味着引用比指针的效率更高,因为在使用引用之前不需要测试它的合法性:指针可以被重新赋值以指向另一个不同的对象,但是引用总是指向它初始化时指定的对象. ...

  9. iOS保持App真后台运行

    https://www.jianshu.com/p/d466f2da0d33 在我看来,苹果系统与安卓系统最直观的区别就是后台处理方式了吧,安卓手机一旦开启了很多app放到后台,即使前台什么也不做,就 ...

  10. 【转】RCP中org.eclipse.core.runtime.CoreException

    org.eclipse.core.runtime.CoreException: Plug-in TRAIN was unable to load class train.Application. 利用 ...