【分块】【链表】bzoj2738 矩阵乘法
http://www.cnblogs.com/jianglangcaijin/p/3460012.html
首先将矩阵的数字排序。设置size,每次将size个数字插入。插入时,我们用h[i][j]记录该位置的数字是否已经插入;用sum[i][j]表示子矩阵(1,1)到(i,j)已经插入的数字个数总和。每次插入后,暴力扫一次询问,若查询子矩阵的数字个数大于等于K则答案就在此次插入的数字中①;然后将该询问从链表中删除。
①怎样知道是插入的哪个数字呢?暴力O(sqrt(n))地扫描当前这段区间,依次判断这个数插入时是否恰好达到k个。
复杂度真心不知道怎么分析了……跪了……
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<list>
using namespace std;
struct Ask{int x1,y1,x2,y2,k,p;
Ask(const int &x){scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k); p=x;}Ask(){}};
list<Ask>Q;
typedef list<Ask>::iterator ITER;
struct Val3{int v,x,y;}Ins[];
bool operator < (const Val3 &a,const Val3 &b){return a.v<b.v;}
int n,m,sumv[][],q,anss[];
bool vis[][];
void makeblock()
{
int sz=sqrt(q),sum=; if(!sz) sz=;
for(;sum*sz<q;++sum)
{
int l=(sum-)*sz+; int r=sum*sz;
for(int i=l;i<=r;++i) vis[Ins[i].x][Ins[i].y]=;
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
sumv[i][j]=sumv[i-][j]+sumv[i][j-]-sumv[i-][j-]+vis[i][j];
ITER it=Q.begin();
while(it!=Q.end())
{
int hav=sumv[(*it).x2][(*it).y2]-sumv[(*it).x1-][(*it).y2]-
sumv[(*it).x2][(*it).y1-]+sumv[(*it).x1-][(*it).y1-];
if(hav>=(*it).k)
{
for(int i=r;i>=l;--i)
if(Ins[i].x>=(*it).x1 && Ins[i].x<=(*it).x2 &&
Ins[i].y>=(*it).y1 && Ins[i].y<=(*it).y2)
{
if(hav==(*it).k)
{
anss[(*it).p]=Ins[i].v;
break;
} --hav;
}
ITER t=it; ++it; Q.erase(t);
}
else ++it;
}
}
int l=(sum-)*sz+; int r=q;
for(int i=l;i<=r;++i) vis[Ins[i].x][Ins[i].y]=;
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
sumv[i][j]=sumv[i-][j]+sumv[i][j-]-sumv[i-][j-]+vis[i][j];
ITER it=Q.begin();
while(it!=Q.end())
{
int hav=sumv[(*it).x2][(*it).y2]-sumv[(*it).x1-][(*it).y2]-
sumv[(*it).x2][(*it).y1-]+sumv[(*it).x1-][(*it).y1-];
if(hav>=(*it).k)
{
for(int i=r;i>=l;--i)
if(Ins[i].x>=(*it).x1 && Ins[i].x<=(*it).x2 &&
Ins[i].y>=(*it).y1 && Ins[i].y<=(*it).y2)
{
if(hav==(*it).k)
{
anss[(*it).p]=Ins[i].v;
break;
} --hav;
}
ITER t=it; ++it; Q.erase(t);
}
else ++it;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
{
scanf("%d",&Ins[++q].v);
Ins[q].x=i; Ins[q].y=j;
}
sort(Ins+,Ins+q+);
for(int i=;i<=m;++i) Q.push_back(Ask(i));
makeblock();
for(int i=;i<=m;++i) printf("%d\n",anss[i]);
return ;
}
【分块】【链表】bzoj2738 矩阵乘法的更多相关文章
- [bzoj2738]矩阵乘法_整体二分_树状数组
矩阵乘法 bzoj-2738 题目大意:给定一个$n*n$的矩阵.每次给定一个矩阵求矩阵$k$小值. 注释:$1\le n\le 500$,$1\le q\le 6\cdot 10^4$. 想法: 新 ...
- BZOJ2738: 矩阵乘法
Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N*N个数,表示这个矩阵: ...
- BZOJ2738矩阵乘法——整体二分+二维树状数组
题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入 第一行两个数N,Q,表示矩阵大小和询问组数:接下来N行N列一共N*N个数,表示这个矩阵:再接下来Q行每行5 ...
- [BZOJ2738]矩阵乘法-[整体二分+树状数组]
Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. (N<=500,Q<=60000) Solution 考虑二分答案,问题转化为求矩阵内为1 ...
- [BZOJ2738]矩阵乘法 整体二分+二维树状数组
2738: 矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1643 Solved: 715[Submit][Status][Discuss ...
- BZOJ2738: 矩阵乘法(整体二分)
Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N*N个数,表示这个矩阵: ...
- BZOJ2738 矩阵乘法 【整体二分 + BIT】
题目链接 BZOJ2738 题解 将矩阵中的位置取出来按权值排序 直接整体二分 + 二维BIT即可 #include<algorithm> #include<iostream> ...
- bzoj2738矩阵乘法
题意: 给你一个N*N的矩阵,没有修改,每次询问一个子矩形中的第K小数. 题目链接 思路: 当它只有一列时,其实就是区间第K大,也就是整体二分可以解决的. 现在到了二维,只需要将之前的树状数组改成二维 ...
- BZOJ2738 矩阵乘法(整体二分+树状数组)
单个询问二分答案即可,多组询问直接整体二分再二维BIT.注意保证复杂度. #include<iostream> #include<cstdio> #include<cma ...
随机推荐
- HDU4370:0 or 1(最短路)
0 or 1 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4370 Description: Given a n*n matrix Cij (1< ...
- ibeacon UUID
import sys; import uuid; s=uuid.uuid4().hex #s="f6bc15e0939046679be1866ec8a199dc" sys.stdo ...
- photo@PKU
- rman异机恢复,全部恢复和增量恢复
1.首先准备工作:hostname 192.168.222.11 ol7.localdomain ol7建立相关目录:mkdir -p /u01/app/oracle/oradata/DB11G/mk ...
- ACM-ICPC 2018 南京赛区网络预赛 Sum
A square-free integer is an integer which is indivisible by any square number except 11. For example ...
- kettle基础操作
ETL:抽取(extract).转换(transform).加载(load)至目的端的过程: Kettle是ETL工具代表之一,是pentaho中的一个数据整合的一个组件.Kettle里包括多个Job ...
- 【Foreign】红与蓝 [暴力]
红与蓝 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 2 2 0 1 -1 -1 2 0 ...
- bzoj 2659 几何
首先考虑(0, 0)到(p, q)这条直线. y = q / p * x. sum{k = 0 to (p - 1) / 2} [q / p * k] 就是直线下方的点数.sum{k = 0 to ( ...
- TASK_KILLABLE:Linux 中的新进程状态【转】
转自:https://www.ibm.com/developerworks/cn/linux/l-task-killable/index.html 新的睡眠状态允许 TASK_UNINTERRUPTI ...
- hdu 3666(差分约束,手动栈解决超时问题)
THE MATRIX PROBLEM Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...