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

来源:互联网 发布:基于php技术的视频直播 编辑:程序博客网 时间:2024/05/01 03:46

题目大意:给定一个矩阵,多次求某个子矩阵中的第k小

分块解法见 http://blog.csdn.net/popoqqq/article/details/41356899

《论除最小割外题目解法从来与题目名称无关系列》

整体二分 Solve(x,y,S)表示处理答案在[x,y]区间内的询问集合S

预先将所有数按照大小排序 每次将[1,mid]之间的数插入树状数组

然后对于分治内部的每一个询问 去树状数组中查询相应子矩阵的数值

如果小于等于k就划分到左集合S1 否则划分到右集合S2

然后Solve(x,mid,S1),Solve(mid+1,y,S2)

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 550using namespace std;struct abcd{int val,x,y;bool operator < (const abcd &a) const{return val < a.val;}}a[M*M];struct query{int x1,y1,x2,y2,k;void Read(){scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);}}mempool[60600],*q[60600],*nq[60600];int n,m,max_num,now;int ans[60600];namespace BIT{int c[M][M];inline void Update(int x,int y,int flag){int i,j;for(i=x;i<=n;i+=i&-i)for(j=y;j<=n;j+=j&-j)c[i][j]+=flag;}inline int Get_Ans(int x,int y){int i,j,re=0;for(i=x;i;i-=i&-i)for(j=y;j;j-=j&-j)re+=c[i][j];return re;}}void Holistic_Bisection(int x,int y,int l,int r){using namespace BIT;int i,mid=x+y>>1;if(l>r) return ;if(x==y){for(i=l;i<=r;i++)ans[q[i]-mempool]=mid;return ;}while( now!=n*n && a[now+1].val<=mid ){++now;Update(a[now].x,a[now].y,1);}while( now && a[now].val>mid ){Update(a[now].x,a[now].y,-1);--now;}int _l=l,_r=r;for(i=l;i<=r;i++){int temp=Get_Ans(q[i]->x2,q[i]->y2)-Get_Ans(q[i]->x1-1,q[i]->y2)-Get_Ans(q[i]->x2,q[i]->y1-1)+Get_Ans(q[i]->x1-1,q[i]->y1-1);if(q[i]->k<=temp)nq[_l++]=q[i];elsenq[_r--]=q[i];}memcpy(q+l,nq+l,sizeof(q[0])*(r-l+1) );Holistic_Bisection(x,mid,l,_l-1);Holistic_Bisection(mid+1,y,_r+1,r);}int main(){int i,j;cin>>n>>m;for(i=1;i<=n;i++)for(j=1;j<=n;j++){scanf("%d",&a[i*n-n+j].val);a[i*n-n+j].x=i;a[i*n-n+j].y=j;max_num=max(max_num,a[i*n-n+j].val);}sort(a+1,a+n*n+1);for(i=1;i<=m;i++){mempool[i].Read();q[i]=&mempool[i];}Holistic_Bisection(0,max_num,1,m);for(i=1;i<=m;i++)printf("%d\n",ans[i]);return 0;}


0 3
原创粉丝点击