您的位置:首页 > 其它

BZOJ 2738 矩阵乘法 整体二分

2017-06-16 15:22 197 查看
题目大意:给出一个N*N的矩阵,每次询问一个子矩形的第K小数。

整体二分即在二分答案的同时把询问分到两个集合中再分别二分直到每个询问出解。

相当于把多个询问一起二分

如何判断一个数x是不是k小呢

把矩阵中的小于等于x的数设为1,大于x的数设为0,求询问矩阵中的小于等于x的数有多少个,大于等于k说明x 有可能是k小。

#include <cstdio>
#include <algorithm>
#define N 505
#define M 60005
#define INF 1000000000
using namespace std;
int n,m;
namespace BIT {
inline int lowbit(int x) { return x&-x; }
int c

;
int Sum(int x,int y) {
int tmp=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
tmp+=c[i][j];
return tmp;
}
void Modify(int x,int y,int v) {
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
c[i][j]+=v;
return ;
}
}
using namespace BIT;
struct Data {
int x,y,v;
Data() {}
Data(int _x,int _y,int _v):x(_x),y(_y),v(_v) {}
bool operator < (const Data& rhs) const { return v<rhs.v; }
void Update(int mode) { Modify(x,y,mode); }
}a[N*N];
struct Query {
int ord,x1,y1,x2,y2,k;
void scan(int _ord) {
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
ord=_ord;
return ;
}
bool check() {
return Sum(x1-1,y1-1)+Sum(x2,y2)-Sum(x1-1,y2)-Sum(x2,y1-1)>=k;
}
}q[M],p[M];
int tot,now,ans[M];
void solve(int L,int R,int l,int r) {
if(L>R || l>r) return ;
int _L=L,_R=R,mid=l+r>>1;
while(now<tot && a[now+1].v<=mid) a[++now].Update(1);
while(now && a[now].v>mid) a[now--].Update(-1);
for(int i=L;i<=R;++i) {
if(q[i].check()) ans[q[i].ord]=mid, p[_L++]=q[i];
else p[_R--]=q[i];
}
for(int i=L;i<=R;++i) q[i]=p[i];
solve(L,_L-1,l,mid-1), solve(_R+1,R,mid+1,r);
return ;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1,x;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&x), a[++tot]=Data(i,j,x);
sort(a+1,a+tot+1);
for(int i=1;i<=m;++i) q[i].scan(i);
solve(1,m,0,INF);
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: