题目大意:给定一个矩阵,多次求某个子矩阵中的第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 550 using 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]; else nq[_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; }