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