题目大意:给定一个矩阵,多次求一个子矩阵中的第k小
正解:CDQ分治 不会
二维莫队? 不会
于是果断分块大法好(又是
我们将这n*n个数排序 分n次插入 每次插入n个
每次插入后 去链表上处理尚未出解的询问(我懒得写链表写了并查集) 如果当前询问的子矩阵内已经插入大于等于k个数 那么答案一定在当次插入的n个数中 暴力查找即可
时间复杂度O(n^3+nq) 好卡……
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 510
using namespace std;
struct abcd{
int x,y,num;
bool operator < (const abcd &Y) const
{
return num < Y.num ;
}
}a[M*M];
struct query{
int x1,y1,x2,y2,k;
}q[60600];
int n,m;
int map[M][M],cnt[M][M],sum[M][M],ans[60600];
int fa[60600];
int Find(int x)
{
if(!fa[x]||fa[x]==x)
return fa[x]=x;
return fa[x]=Find(fa[x]);
}
int main()
{
int i,j,k;
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
a[i*n-n+j].x=i;
a[i*n-n+j].y=j;
a[i*n-n+j].num=map[i][j];
}
for(i=1;i<=m;i++)
scanf("%d%d%d%d%d",&q[i].x1,&q[i].y1,&q[i].x2,&q[i].y2,&q[i].k);
sort(a+1,a+n*n+1);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
abcd &temp=a[i*n-n+j];
cnt[temp.x][temp.y]=1;
}
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
sum[j][k]=cnt[j][k]+sum[j-1][k]+sum[j][k-1]-sum[j-1][k-1];
for(k=Find(1);k<=m;k=Find(k+1))
{
int x1=q[k].x1-1;
int y1=q[k].y1-1;
int x2=q[k].x2;
int y2=q[k].y2;
int temp=sum[x2][y2]+sum[x1][y1]-sum[x1][y2]-sum[x2][y1];
if(temp<q[k].k)
continue;
temp-=q[k].k;
for(j=n;j;j--)
if(a[i*n-n+j].x>x1&&a[i*n-n+j].y>y1&&a[i*n-n+j].x<=x2&&a[i*n-n+j].y<=y2)
if(!temp--)
{
ans[k]=a[i*n-n+j].num;
break;
}
fa[k]=k+1;
}
}
for(i=1;i<=m;i++)
printf("%d\n",ans[i]);
}