[noi.ac] 列队

问题描述

快开学了,小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\n",sum[x][y]);
	}
	return 0;
}
posted @ 2020-02-13 22:40  CJlzf  阅读(183)  评论(0编辑  收藏  举报