poj2019 Cornfields RMQ

来源:互联网 发布:知美术馆电话 编辑:程序博客网 时间:2024/05/21 20:28

给出一个N*N (N<=250)的方阵,以及K(<=100000)个询问。每次询问如下:以(Xi,Yi)为左上角,边长为B的子方阵中,最大值和最小值的差是多少?

注意对于所有的询问,B都是一个定值。

Input
第一行N,B(<=N),K。含义如上。

接下来N行N列的一个矩阵,每个数<=250。

接下来K行表示询问,每行两个数Xi, Yi 表示询问的方阵的左上角。

Output
一行一个正整数,含义如上。

Sample Input
5 3 1
5 1 2 6 3
1 3 5 2 7
7 2 4 6 1
9 9 8 6 5
0 6 9 3 9
1 2
Sample Output
5

提前对每一列进行RMQ(我写的RIQ表示计算最小值)

代码:

#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <map>#define MST(s,q) memset(s,q,sizeof(s))#define INF 0x3f3f3f3f#define MAXN 255#define Lchild id<<1#define Rchild (id<<1)+1using namespace std;int  arr[MAXN][MAXN], rmq[MAXN][MAXN][10], riq[MAXN][MAXN][10];void init(int k, int N) {    for (int i = 1; i <= N; i++)        rmq[k][i][0] = arr[i][k], riq[k][i][0] = arr[i][k];    for (int j = 1; (1 << j) <= N; j++)        for (int i = 1; i + (1 << j) - 1 <= N; i++) {            rmq[k][i][j] = max(rmq[k][i][j - 1], rmq[k][i + (1 << (j - 1))][j - 1]);            riq[k][i][j] = min(riq[k][i][j - 1], riq[k][i + (1 << (j - 1))][j - 1]);        }}int RMQ(int k, int i, int j) {    int p = (int)(log(j - i + 1) / log(2));    return max(rmq[k][i][p], rmq[k][j - (1 << p) + 1][p]);}int RIQ(int k, int i, int j) {    int p = (int)(log(j - i + 1) / log(2));    return min(riq[k][i][p], riq[k][j - (1 << p) + 1][p]);}int main() {    int N, B, K, a, b;    cin >> N >> B >> K;    for (int i = 1; i <= N; i++)        for (int j = 1; j <= N; j++)            scanf("%d", &arr[i][j]);    for (int i = 1; i <= N; i++) init(i, N);    int ans_max, ans_min;    while (K--) {        scanf("%d%d", &a, &b);        ans_max = -99999999, ans_min = INF;        for (int i = b; i < b + B; i++) {            ans_max = max(RMQ(i, a, a + B - 1), ans_max);            ans_min = min(RIQ(i, a, a + B - 1), ans_min);        }        printf("%d\n", ans_max - ans_min );    }}
0 0
原创粉丝点击