zoukankan      html  css  js  c++  java
  • 二维 ST POJ 2019

    题目大意:给你一个n*n的矩阵,每次给你一个点(x,y),以其为左上角,宽度为b的矩阵中最小的数值和最大数值的差是多少?  一共k个询问。

    思路:简单的二维st。

    定义dp(i,j,k,L)表示以(i,j)为左上角,宽度为(2^k, 2^L)的区间内的最大(小)值。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    #include<utility>
    #include<stdlib.h>
    #include<time.h>
    #include<cmath>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 250 + 5;
    int dp[maxn][maxn][8][8], dp2[maxn][maxn][8][8];
    int n, b, k;
    
    void init_st(){
        for (int i = 0; (1 << i) <= n; i++){
            for (int j = 0; (1 << j) <= n; j++){
                if (i == 0 && j == 0) continue;
                for (int x = 1; x + (1 << i) - 1 <= n; x++){
                    for (int y = 1; y + (1 << j) - 1 <= n; y++){
                        if (i == 0) {
                            dp[x][y][i][j] = min(dp[x][y][i][j - 1], dp[x][y + (1 << (j - 1))][i][j - 1]);
                            dp2[x][y][i][j] = max(dp2[x][y][i][j - 1], dp2[x][y + (1 << (j - 1))][i][j - 1]);
                        }
                        else {
                            dp[x][y][i][j] = min(dp[x][y][i - 1][j], dp[x + (1 << (i - 1))][y][i - 1][j]);
                            dp2[x][y][i][j] = max(dp2[x][y][i - 1][j], dp2[x + (1 << (i - 1))][y][i - 1][j]);
                        }
                    }
                }
            }
        }
    }
    
    int query(int x, int y, int X, int Y){
        int maxi = 0, mini = 1e8;
        int k1 = 0, k2 = 0;
        while (1 << (1 + k1) <= X - x) k1++;
        while (1 << (1 + k2) <= Y - y) k2++;
        maxi = max(maxi, max(dp2[x][y][k1][k2], dp2[X - (1 << k1) + 1][y][k1][k2]));
        maxi = max(maxi, max(dp2[x][Y - (1 << k2) + 1][k1][k2], dp2[X - (1 << k1) + 1][Y - (1 << k2) + 1][k1][k2]));
    
        mini = min(mini, min(dp[x][y][k1][k2], dp[X - (1 << k1) + 1][y][k1][k2]));
        mini = min(mini, min(dp[x][Y - (1 << k2) + 1][k1][k2], dp[X - (1 << k1) + 1][Y - (1 << k2) + 1][k1][k2]));
        //printf("maxi = %d mini = %d
    ", maxi, mini);
        return maxi - mini;
    }
    
    int main(){
        //while (true){
        cin >> n >> b >> k;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                scanf("%d", &dp[i][j][0][0]);
                dp2[i][j][0][0] = dp[i][j][0][0];
            }
        }
        init_st();
        for (int i = 1; i <= k; i++){
            int x, y; scanf("%d%d", &x, &y);
            int ans = query(x, y, x + b - 1, y + b - 1);
            printf("%d
    ", ans);
        }
        //}
        return 0;
    }
    View Code
  • 相关阅读:
    VC++删除浮动工具条中“关闭”按钮
    automation无法创建对象
    SQL Server 不产生日志
    收缩数据文件
    VB DoEvents用法
    Sql Server添加用户
    Winsock错误代码一览表
    监控数据库性能的sql
    数据库日志文件清理脚本
    VB 中资源文件的多种使用技巧
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6105383.html
Copyright © 2011-2022 走看看