题目链接 BZOJ
洛谷

整体二分。把求序列第K小的树状数组改成二维树状数组就行了。
初始答案区间有点大,离散化一下。

因为这题是一开始给点,之后询问,so可以先处理该区间值在l~mid的修改,再处理询问。即二分标准可以直接用点的标号。
结构体的赋值可以改为赋值操作的编号。(这样内存没那么连续?想多了你)

改了半下午,优化了500ms。。

//6980kb    10584ms 好慢啊QAQ
//4208ms    7.59MB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define lb(x) ((x)&-(x))
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=505,M=60005;int n,m,Ans[M],q[M],q1[M],q2[M];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Point
{int x,y,val;Point() {}Point(int x,int y,int val):x(x),y(y),val(val) {}bool operator <(const Point &a)const{return val<a.val;}
}pt[N*N];
inline int read();
struct Operation//Query
{int K,x1,y1,x2,y2;inline void Input(){x1=read(),y1=read(),x2=read(),y2=read(),K=read();}
}op[M];inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
namespace T
{int n,t[N][N];inline void Modify(int x,int y,int v){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j)) t[i][j]+=v;}inline void Clear(int x,int y){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j))if(t[i][j]) t[i][j]=0; else break;}inline int Query(int x,int y){int res=0;for(int i=x; i; i^=lb(i))for(int j=y; j; j^=lb(j)) res+=t[i][j];return res;}inline int Query_Area(Operation q){//prefix sumreturn Query(q.x2,q.y2)-Query(q.x1-1,q.y2)-Query(q.x2,q.y1-1)+Query(q.x1-1,q.y1-1);}
}
void Solve(int l,int r,int h,int t)
{if(h>t) return;if(l==r){for(int i=h; i<=t; ++i) Ans[q[i]]/*[op[q[i]].pos]*/=pt[l].val;return;}int mid=l+r>>1, t1=0, t2=0;for(int i=l; i<=mid; ++i) T::Modify(pt[i].x,pt[i].y,1);for(int now,tmp,i=h; i<=t; ++i){now=q[i], tmp=T::Query_Area(op[now]);if(tmp>=op[now].K) q1[t1++]=now;else op[now].K-=tmp, q2[t2++]=now;}for(int i=l; i<=mid; ++i) T::Clear(pt[i].x,pt[i].y);for(int i=0; i<t1; ++i) q[h+i]=q1[i];for(int i=0; i<t2; ++i) q[h+t1+i]=q2[i];Solve(l,mid,h,h+t1-1), Solve(mid+1,r,h+t1,t);
}int main()
{T::n=n=read(), m=read();int tot=0;for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j) pt[++tot]=Point(i,j,read());std::sort(pt+1,pt+1+tot);for(int i=1; i<=m; ++i) q[i]=i, op[i].Input();Solve(1,tot,1,m);for(int i=1; i<=m; ++i) printf("%d\n",Ans[i]);return 0;
}

优化前:

//4680ms    17.75MB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define lb(x) ((x)&-(x))
//#define gc() getchar()
#define MAXIN 60000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=505,M=60005+N*N;int n,m,Q,cnt,A[N*N],Ans[60005];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Operation
{int K,x1,y1,x2,y2,pos;//K=0: Modify (x1,y1):=posOperation() {}Operation(int K,int x1,int y1,int x2,int y2,int pos):K(K),x1(x1),y1(y1),x2(x2),y2(y2),pos(pos) {}
}q[M],q1[M],q2[M];inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
namespace T
{int n,t[N][N];inline void Modify(int x,int y,int v){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j)) t[i][j]+=v;}inline void Clear(int x,int y){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j))if(t[i][j]) t[i][j]=0; else break;}inline int Query(int x,int y){int res=0;for(int i=x; i; i^=lb(i))for(int j=y; j; j^=lb(j)) res+=t[i][j];return res;}inline int Query_Area(Operation q){//prefix sumreturn Query(q.x2,q.y2)-Query(q.x1-1,q.y2)-Query(q.x2,q.y1-1)+Query(q.x1-1,q.y1-1);}
}
void Solve(int l,int r,int h,int t)
{if(h>t) return;if(l==r){for(int i=h; i<=t; ++i) if(q[i].K) Ans[q[i].pos]=A[l];return;}bool goon=0;for(int i=h; i<=t; ++i) if(q[i].K) {goon=1; break;}if(!goon) return;int mid=l+r>>1, midV=A[mid], t1=0, t2=0;for(int i=h; i<=t; ++i)if(q[i].K){int tmp=T::Query_Area(q[i]);//这样好像少做几次加法!但是多copy两个int。。(你够了→_→)if(tmp>=q[i].K) q1[t1++]=q[i];else q[i].K-=tmp, q2[t2++]=q[i];}else{if(q[i].pos<=midV) T::Modify(q[i].x1,q[i].y1,1), q1[t1++]=q[i];else q2[t2++]=q[i];}for(int i=0; i<t1; ++i) if(!q1[i].K) T::Clear(q1[i].x1,q1[i].y1);for(int i=0; i<t1; ++i) q[h+i]=q1[i];for(int i=0; i<t2; ++i) q[h+t1+i]=q2[i];Solve(l,mid,h,h+t1-1), Solve(mid+1,r,h+t1,t);
}int main()
{T::n=n=read(), m=read(), Q=0;for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j) q[++Q]=Operation(0,i,j,0,0,A[Q]=read());std::sort(A+1,A+1+Q), cnt=1;for(int i=2; i<=Q; ++i) if(A[i]!=A[i-1]) A[++cnt]=A[i];for(int x1,y1,x2,y2,i=1; i<=m; ++i)x1=read(),y1=read(),x2=read(),y2=read(),q[++Q]=Operation(read(),x1,y1,x2,y2,i);Solve(1,cnt,1,Q);for(int i=1; i<=m; ++i) printf("%d\n",Ans[i]);return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/9234335.html

BZOJ.2738.矩阵乘法(整体二分 二维树状数组)相关推荐

  1. P1527 [国家集训队]矩阵乘法 整体二分 + 二维树状数组

    传送门 题意: 思路: 算是个整体二分的板子啦,不过这个是二维的矩阵,我们只需要把一位树状数组改成二维的,让后动态维护单点加,区间查询前缀和即可. //#pragma GCC optimize(2) ...

  2. jzoj2908,P1527-[集训队互测 2012]矩阵乘法【整体二分,二维树状数组】

    正题 题目链接:https://www.luogu.org/problem/P1527 题目大意 给出一个矩阵,每个询问求子矩阵中的第kkk小数. 解题思路 我们发现我们对于每个询问我们可以二分答案, ...

  3. BZOJ 2738: 矩阵乘法 [整体二分]

    给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 愚蠢的名字...... 整体二分,影响因子就是矩阵里的数 把$\le mid$的矩阵元素加到二维树状数组里然后询问分成两组就行 ...

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

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

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

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

  6. 二维树状数组 BZOJ 1452 [JSOI2009]Count

    题目链接 裸二维树状数组 #include <bits/stdc++.h>const int N = 305; struct BIT_2D {int c[105][N][N], n, m; ...

  7. 【二维树状数组】See you~

    https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A ...

  8. szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】

    树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...

  9. 海啸(二维前缀和/二维树状数组)

    链接:https://ac.nowcoder.com/acm/problem/21862 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

最新文章

  1. usaco Beef McNuggets
  2. 一口气用 Python 写了13个小游戏,摸鱼达人!
  3. 密码学研究-玩转密钥
  4. 针对蓝牙4.0 BLE通讯过程的逆向和攻击
  5. 百度编辑器修改,不让它自动替换html标签
  6. 自己建文件111 txt python_这可能是最详细的Python文件操作
  7. linux time 统计命令执行的时间
  8. Linux基础——linux和gcc的介绍
  9. 搭建LVS_DR模型
  10. 我在德国做SAP CRM One Order redesign工作的心得
  11. LeetCode-665:非递减数列
  12. Oracle中关于处理小数点位数的几个函数,取小数位数,Oracle查询函数
  13. Coregistration: Simultaneous Alignment and Modeling of Articulated 3D Shape
  14. 微服务架构如何实现网站服务垂直化拆分
  15. 14、任务十四——数组对象的处理、修改DOM中的内容
  16. Python:每日一题008
  17. Atitit tomcat在linux服务器的启动与其他
  18. yuv 420 mp4 flv 视频与acc 各类音视频测试下载地址
  19. 利用melendy插入参考文献_Q基因的转座子插入突变导致去驯化过程中普通小麦重获脆穗性...
  20. 法国内政部选择由金雅拓保护该国关键的通信移动网络

热门文章

  1. android baseactivity,Android应用开发Android通过BaseActivity获取到当前启动的Activity名称...
  2. qregexp括号匹配_转:Qt的正则表达式和QRegExp
  3. linux db2sysc 内存,db2sysc进程占用linux内存持续增长,请各位指点。
  4. has_a php,PHP has encountered a Stack overflow问题解决方法
  5. 程序员都用什么来记录知识_1年前的小五都用 Python 来做什么?
  6. python中print的用法_Python中print函数简单使用总结
  7. 法律专业计算机基础试卷答案,大学计算机基础试题及答案
  8. LintCode 375. 克隆二叉树(深复制)
  9. rtmp协议分析(三次握手)
  10. 线性表----链式表