问题描述
快开学了,小W正在军训。
他们班一共有 n∗m 位同学,于是列队的时候,教官让他们站成了 n 排 m 列。小W发现,如果一个人的身高在他所在的那一排是最高的,在那一列也是最高的,那么他会很显眼。由于列队过于无聊,小W开始计算有多少人非常显眼。
这显然难不倒他,于是他想计算有多少人是他所在排第 x 高的,在他所在列是第 y 高的。小W要忙着应付教官了,所以他没有时间来算了,于是他找来了没在军训的你帮他算一算。他可能有很多询问,你需要快速回答所有的询问。
输入格式
第一行三个整数 n,m,q。
接下来 n 行,每行 m 个整数,代表第 i 行第 j 列的整数 hi,j 表示第 i 排第 j 列的人的身高。保证 [1,n∗m] 的每个整数出现且仅出现一次。
接下来 q 行,每行两个整数 x,y,表示一组询问。
输出格式
输出共 q 行,每行一个整数,表示第 i 组询问的答案。
样例输入
3 3 2
1 8 9
3 2 7
6 5 4
3 3
2 2
样例输出
3
2
数据范围
n,m≤1000,q≤5∗10^5
解析
暴力队每一行、每一列进行排序,我们可以直接统计出每个点在它所在的行、列上有多少个数比它大。然后就知道它在行、列上的排名了。简单记录一下,然后直接回答询即可。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 1002
using namespace std;
struct node{
int h,x,y,id;
}a[N*N],b[N];
int n,m,q,i,j,sum[N][N];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
int id(int x,int y)
{
return (x-1)*m+y;
}
int my_comp(const node &x,const node &y)
{
return x.h>y.h;
}
int main()
{
n=read();m=read();q=read();
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
int p=id(i,j);
a[p].h=read();
a[p].id=p;
}
}
for(i=1;i<=n;i++){
int tmp=0;
for(j=1;j<=m;j++) b[++tmp]=a[id(i,j)];
sort(b+1,b+m+1,my_comp);
for(j=1;j<=m;j++) a[b[j].id].x=j;
}
for(i=1;i<=m;i++){
int tmp=0;
for(j=1;j<=n;j++) b[++tmp]=a[id(j,i)];
sort(b+1,b+n+1,my_comp);
for(j=1;j<=n;j++) a[b[j].id].y=j;
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
int p=id(i,j);
sum[a[p].x][a[p].y]++;
}
}
for(i=1;i<=q;i++){
int x=read(),y=read();
printf("%d
",sum[x][y]);
}
return 0;
}