[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;
}

猜你喜欢

转载自www.cnblogs.com/LSlzf/p/12305687.html