zoukankan      html  css  js  c++  java
  • 二维ST表

    二维ST表。

    ​ 二维ST表咋写捏?

    (f[x][y][k][l])表示左上角为((x, y)),右下角为((x + 2^{k} -1 , y+2^l - 1))的矩形内的最值是多少。

    ​ 转移的话和原来差不多,首先可以将矩形从中间横着劈一刀:

    (f[x][y][k][l] = max/min(f[x][y][k - 1][l], f[x + 2 ^ {k - 1}][y][k - 1][l]))

    ​ 然后还可以将矩形从中间竖着劈一刀:

    (f[x][y][k][l] = max/min(f[x][y][k][l - 1], f[x][y + 2^{l - 1}][k][l - 1]))

    ​ 同样的,还是可以实现(O(1))查询,假设现在要查询左上角为((x1, y1)),右下角为((x2 , y2))的矩形内的最值是多少。

    ​ 设(p = lg[x2 - x1 + 1], q = lg[y2 - y1 + 1])

    ​ 如图我们可以把查询的大矩形分为四个小矩形,他们的坐标分别是:
    ((x1, y1, x1 + 2^p - 1, y1 + 2^q - 1)),
    ((x1, y2 - 2 ^ q + 1, x2 - 2^p + 1, y2)),
    ((x2 - 2 ^ p + 1, y1, x2, y2 - 2^q + 1)),
    ((x2 - 2^p + 1, y2 - 2^k + 1, x2, y2))
    分别对应图上的(w1,w2,w3,w4)。对这四个小矩形的最值取(max/min),就是大矩形的最值了。

    P2216 [HAOI2007]理想的正方形

    ​ 这道题可用二维ST表做。

    题目链接

    ​ 对于这道题直接开(f[1005][1005][11][11])是会爆空间的,但是我们发现题目要求的是正方形,其实就可以省去第三,四维;直接维护每个正方形的值就好了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f;
    }
    
    const int N = 1005, inf = 2e9;
    int n, m, k, ans;
    int lg[N], f[N][N], g[N][N];
    
    int main() {
    
        n = read(); m = read(); k = read();
        for(int i = 1;i <= n; i++)
            for(int j = 1;j <= m; j++) f[i][j] = g[i][j] = read();
    
        
        lg[0] = -1;
        for(int i = 1;i <= k; i++) lg[i] = lg[i >> 1] + 1;
    
        for(int s = 1;s <= lg[k]; s++) 
            for(int i = 1;i + (1 << s) - 1 <= n; i++)
                for(int j = 1;j + (1 << s) - 1 <= m; j++) {
                    f[i][j] = max(max(f[i][j], f[i][j + (1 << (s - 1))]), max(f[i + (1 << (s - 1))][j], f[i + (1 << (s - 1))][j + (1 << (s - 1))]));
                    g[i][j] = min(min(g[i][j], g[i][j + (1 << (s - 1))]), min(g[i + (1 << (s - 1))][j], g[i + (1 << (s - 1))][j + (1 << (s - 1))]));
                }
    
        ans = inf;
        for(int i = 1;i + k - 1 <= n; i++)
            for(int j = 1;j + k - 1 <= m; j++) {
                int x = i + k - 1, y = j + k - 1; 
                int maxn = max(max(f[i][j], f[x - (1 << lg[k]) + 1][j]), max(f[i][y - (1 << lg[k]) + 1], f[x - (1 << lg[k]) + 1][y - (1 << lg[k]) + 1]));
                int minn = min(min(g[i][j], g[x - (1 << lg[k]) + 1][j]), min(g[i][y - (1 << lg[k]) + 1], g[x - (1 << lg[k]) + 1][y - (1 << lg[k]) + 1]));
                ans = min(ans, maxn - minn);
            }
        
        printf("%d
    ", ans);
    
        return 0;
    }
    
  • 相关阅读:
    mvn package打包提示:Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources
    [Android] 【手机定位他迹】最新破解版 ,解锁VIP会员,去除广告绿化等等
    Python编程:从入门到实践超清版及全书源代码
    Win11永久激活工具 (可激活win10) + 注册码+Win11 正式版发布 版本号22000.194
    通过命令为 Elementary OS 窗口添加最小化按钮
    inno setup 通过指针获取完整字符串(宽字节字符)
    竹子开花
    屋后有靠山生万福
    自然吸气和涡轮增压哪个好 按需选择是关键
    父母对钱的态度,影响孩子的一生
  • 原文地址:https://www.cnblogs.com/czhui666/p/13693835.html
Copyright © 2011-2022 走看看