题目传送门

矩阵乘法

题目描述

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

输入输出格式

输入格式:

第一行两个数N,Q,表示矩阵大小和询问组数;

接下来N行N列一共N*N个数,表示这个矩阵;

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

输出格式:

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

输入输出样例

输入样例#1:

2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3
输出样例#1:

1
3

说明

矩阵中数字是10^9以内的非负整数;

20%的数据:N<=100,Q<=1000;

40%的数据:N<=300,Q<=10000;

60%的数据:N<=400,Q<=30000;

100%的数据:N<=500,Q<=60000。


  分析:

  是的,这道题虽然叫矩阵乘法,但是和矩阵乘法一点关系都没有。

  求矩阵$k$小就能想到用整体二分,不过因为是二维,所以需要用二维树状数组,然后写法需要漂亮一点,因为这题有点卡常。

  另外,有一点需要讲一下,平常我写树状数组都是这样的:

inline void add(int pos,int x)
{
for(; pos<=n; pos+=lowbit(pos)) c[pos]+=x;
}

  但是在二维树状数组中就不能这么写,应该写成:

inline void add(int x,int y,int v)
{
for(int i=x; i<=n; i+=lowbit(i))
for(int j=y; j<=n; j+=lowbit(j)) c[i][j]+=v;
}

  Code:

//It is made by HolseLee on 6th Oct 2018
//Luogu.org P1527
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N=4e5+;
int n,m,cnt,c[][],q1[N],q2[N],id[N],ans[N];
struct Node {
int x,y,v;
Node() {}
Node(const int _x,const int _y,const int _v):
x(_x), y(_y), v(_v) {}
bool operator < (const Node a) const {
return v < a.v;
}
}a[N];
struct Qus {
int x1,y1,x2,y2,k;
}q[N]; inline int read()
{
char ch=getchar(); int num =; bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' ) flag=true; ch=getchar();
}
while( ch>='' && ch<='' ) {
num=num*+ch-''; ch=getchar();
}
return flag ? -num : num;
} inline int lowbit(int x)
{
return x&(-x);
} inline void add(int x,int y,int v)
{
for(int i=x; i<=n; i+=lowbit(i))
for(int j=y; j<=n; j+=lowbit(j)) c[i][j]+=v;
} inline int quary(int x,int y)
{
int ret=;
for(int i=x; i; i-=lowbit(i))
for(int j=y; j; j-=lowbit(j)) ret+=c[i][j];
return ret;
} inline int get(int x1,int y1,int x2,int y2)
{
return quary(x2,y2)-quary(x1-,y2)-quary(x2,y1-)+quary(x1-,y1-);
} void solve(int l,int r,int L,int R)
{
if( l>r || L>R ) return;
if( l==r ) {
for(int i=L; i<=R; ++i) ans[id[i]]=a[l].v;
return;
}
int mid=(l+r)>>, cnt1=, cnt2=;
for(int i=l; i<=mid; ++i) add(a[i].x,a[i].y,);
for(int i=L; i<=R; ++i) {
int tmp=get(q[id[i]].x1,q[id[i]].y1,q[id[i]].x2,q[id[i]].y2);
if( tmp>=q[id[i]].k ) q1[++cnt1]=id[i];
else q[id[i]].k-=tmp, q2[++cnt2]=id[i];
}
for(int i=l; i<=mid; ++i) add(a[i].x,a[i].y,-);
for(int i=; i<=cnt1; ++i) id[L+i-]=q1[i];
for(int i=; i<=cnt2; ++i) id[L+cnt1+i-]=q2[i];
solve(l,mid,L,L+cnt1-); solve(mid+,r,L+cnt1,R);
} int main()
{
n=read(), m=read();
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j){
a[++cnt]=Node(i,j,read());
}
sort(a+,a+cnt+);
for(int i=; i<=m; ++i) {
q[i].x1=read(), q[i].y1=read(), q[i].x2=read(), q[i].y2=read();
q[i].k=read(); id[i]=i;
}
solve(,cnt,,m);
for(int i=; i<=m; ++i) printf("%d\n",ans[i]);
return ;
}

洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]的更多相关文章

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

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

  2. 洛谷$P1527$ [国家集训队]矩阵乘法 整体二分

    正解:整体二分 解题报告: 传送门$QwQ$ 阿看到这种查询若干次第$k$小显然就想到整体二分$QwQ$? 然后现在就只要考虑怎么快速求出一个矩形内所有小于某个数的数的个数? 开始我的想法是离散化然后 ...

  3. BZOJ2738矩阵乘法——整体二分+二维树状数组

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

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

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

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

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

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

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

  7. 洛谷 P1527 [国家集训队]矩阵乘法 解题报告

    P1527 [国家集训队]矩阵乘法 题目描述 给你一个\(N*N\)的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第\(K\)小数. 输入输出格式 输入格式: 第一行两个数\(N,Q\),表示矩阵大 ...

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

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

  9. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

随机推荐

  1. idea 安装lombok 插件过程

    一.作用 Lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,bean,entity等类,绝大部分数据类类中都需要get.set.toStrin ...

  2. Donald Ervin Knuth:最年轻的图灵奖高德纳

    高德纳(Donald Ervin Knuth,1938年),美国著名计算机科学家,斯坦福大学电脑系荣誉教授.高德纳教授被誉为现代计算机科学的鼻祖,在计算机科学及数学领域发表了多部 具广泛影响的论文和著 ...

  3. 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT

    [题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...

  4. td自动换行

    自动换行方法: 1.在<td>中设置样式style为word-wrap:break-word;word-break:break-all; (一般情况只需要设置word-break:brea ...

  5. 【转】WireShark 过滤规则

    原链:[渗透神器系列]WireShark wireshark是一款网络流量抓取分析神器,也是安全工具使用排行中排名第一的工具.使用wireshark必须要牢记一些常用的数据包过滤规则,对于寻找一些特定 ...

  6. Linux基础-网络配置

    任务目标:临时配置网络ip,网关,DNS,然后重启network:写配置文件永久保存网络配置 临时配置ens33网卡IP地址为192.168.30.99,查看更改完的ifconfig信息: 重新启动n ...

  7. 差分约束系统+输出路径(I - Advertisement POJ - 1752 )

    题目链接:https://cn.vjudge.net/contest/276233#problem/I 题目大意:输入k和n,然后输入n行,每一次输入两个数,代表开端和结尾,如果这个区间内点的个数大于 ...

  8. 2016.6.19——C++杂记

    C++杂记 补充的小知识点: 1.while(n--)和while(--n)区别: while(n--)即使不满足也执行一次循环后跳出. while(--n)不满足直接跳出循环,不执行语句. 用cou ...

  9. 【洛谷题解】P2303 [SDOi2012]Longge的问题

    题目传送门:链接. 能自己推出正确的式子的感觉真的很好! 题意简述: 求\(\sum_{i=1}^{n}gcd(i,n)\).\(n\leq 2^{32}\). 题解: 我们开始化简式子: \(\su ...

  10. MVC中检测到有潜在危险的 Request.Form 值

    在做mvc项目时,当使用xhedit or.ueditor编辑器时,点击提交时,编辑器中的内容会带有html标签提交给服务器,这时就是会报错,出现如下内容: “/”应用程序中的服务器错误. 从客户端( ...