Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 841 Solved: 351
[Submit][Status][Discuss]
Description
给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
Input
第一行两个数N,Q,表示矩阵大小和询问组数;
接下来N行N列一共N*N个数,表示这个矩阵;
再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
Output
对于每组询问输出第K小的数。
Sample Input
2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3
Sample Output
1
3
HINT
矩阵中数字是109以内的非负整数;
20%的数据:N<=100,Q<=1000;
40%的数据:N<=300,Q<=10000;
60%的数据:N<=400,Q<=30000;
100%的数据:N<=500,Q<=60000。
思路题+整体二分。
首先把矩阵中的元素升序排序,然后就可以整体二分了。
即二分每个询问矩阵是在第几大的元素加的时候达到了
和【BZOJ 2527】一样了。
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define M 500005
using namespace std;
struct jz
{
int x,y,v;
}a[M];
struct Query
{
int x1,y1,x2,y2,k,id,cur;
}q[M],b[M];
int t[505][505],ans[M],n,Q;
bool cmp(jz a,jz b)
{
return a.v<b.v;
}
int lowbit(int x)
{
return x&(-x);
}
void Update(int x,int y,int k)
{
if (!x) x++;
if (!y) y++;
for (int i=x;i<=n;i+=lowbit(i))
for (int j=y;j<=n;j+=lowbit(j))
t[i][j]+=k;
}
int sum(int x,int y)
{
int ans=0;
for (int i=x;i>0;i-=lowbit(i))
for (int j=y;j>0;j-=lowbit(j))
ans+=t[i][j];
return ans;
}
int Getsum(int x)
{
return sum(b[x].x2,b[x].y2)-sum(b[x].x2,b[x].y1-1)-sum(b[x].x1-1,b[x].y2)+sum(b[x].x1-1,b[x].y1-1);
}
void read(int &tmp)
{
tmp=0;
char ch=getchar();
int fu=1;
for (;ch<‘0‘||ch>‘9‘;ch=getchar())
if (ch==‘-‘) fu=-1;
for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar())
tmp=tmp*10+ch-‘0‘;
tmp*=fu;
}
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[b[i].id]=a[l].v;
return;
}
int mid=(l+r)>>1;
for (int i=l;i<=mid;i++)
Update(a[i].x,a[i].y,1);
int t1=h-1,t2=t+1;
for (int i=h;i<=t;i++)
{
int tmp=Getsum(i);
if (tmp+b[i].cur>=b[i].k) q[++t1]=b[i];
else b[i].cur+=tmp,q[--t2]=b[i];
}
for (int i=h;i<=t;i++)
b[i]=q[i];
for (int i=l;i<=mid;i++)
Update(a[i].x,a[i].y,-1);
Solve(l,mid,h,t1);
Solve(mid+1,r,t2,t);
}
int main()
{
scanf("%d%d",&n,&Q);
int now=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
read(a[++now].v),a[now].x=i,a[now].y=j;
sort(a+1,a+1+now,cmp);
for (int i=1;i<=Q;i++)
read(b[i].x1),read(b[i].y1),read(b[i].x2),read(b[i].y2),read(b[i].k),
b[i].id=i,b[i].cur=0;
Solve(1,now,1,Q);
for (int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
return 0;
}
原文地址:http://blog.csdn.net/regina8023/article/details/45664415