二维st表,一种暴力但却快速的二维RMQ利器

先上例题:[HAOI2007]理想的正方形 大部分人都用单调队列,但我不会。首先我们可以暴力枚举所有的可能的正方形,每次我们需要查询RMQ,如果用朴素的方法总复杂度就会变成N^4,你不T谁T

那怎么办,总不可能写正解吧,我们可以用二维st表,预处理N^2logN,每次O(1)查询,N^2水过。

注意,强制类型转换要用大括号括起要转换的东西,例如 (int)(log(n)/log(2));

Code:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
#define zmd main
int a,b,n;
int sta[1026][1026][12],sti[1026][1026][12];
int kk;
inline int query1(int x,int y,int xx,int yy)
{
    int t1=sta[x][y][kk],t2=sta[xx-(1<<kk)+1][y][kk],t3=sta[x][yy-(1<<kk)+1][kk],t4=sta[xx-(1<<kk)+1][yy-(1<<kk)+1][kk];
    return max(max(max(t1,t2),t3),t4);
}
inline int query2(int x,int y,int xx,int yy)
{
    int t1=sti[x][y][kk],t2=sti[xx-(1<<kk)+1][y][kk],t3=sti[x][yy-(1<<kk)+1][kk],t4=sti[xx-(1<<kk)+1][yy-(1<<kk)+1][kk];
    return min(min(min(t1,t2),t3),t4);
}
inline int Max(int a,int b,int c,int d)
{
    return max(max(max(a,b),c),d);
}
inline int Min(int a,int b,int c,int d)
{
    return min(min(min(a,b),c),d);
}
int zmd()
{
    std::cin>>a>>b>>n;
    for (int i=1;i<=a;++i) for (int j=1,tmp;j<=b;++j) {scanf("%d",&tmp);sta[i][j][0]=sti[i][j][0]=tmp;}
    int shit=min(a,b);
    for (int k=1;k<=11;++k)
        for (int i=1;i+(1<<k)-1<=a;++i)
            for (int j=1;j+(1<<k)-1<=b;++j)
            {
                sta[i][j][k]=Max(sta[i][j][k-1],sta[i+(1<<k-1)][j][k-1],sta[i][j+(1<<k-1)][k-1],sta[i+(1<<k-1)][j+(1<<k-1)][k-1]);
                sti[i][j][k]=Min(sti[i][j][k-1],sti[i+(1<<k-1)][j][k-1],sti[i][j+(1<<k-1)][k-1],sti[i+(1<<k-1)][j+(1<<k-1)][k-1]);
            }
    kk=(int)(log(n)/log(2));
    int ans=0x3f3f3f3f;
    for (int i=1;i+n-1<=a;i++)
    for (int j=1;j+n-1<=b;j++)
        ans=std::min(ans,query1(i,j,i+n-1,j+n-1)-query2(i,j,i+n-1,j+n-1));
    cout<<ans;
    return 0;
}

原文地址:https://www.cnblogs.com/bullshit/p/9583359.html

时间: 2024-10-17 03:26:03

二维st表,一种暴力但却快速的二维RMQ利器的相关文章

POJ2019 Cornfields 二维ST表

网址:https://vjudge.net/problem/POJ-2019 题意: 给出一个矩阵,求左下角坐标为$(x,y)$,长度为$b$的正方形的包含的数的最大值和最小值. 题解: 一.二维ST表: 一维$ST$表可以快速处理一维$RMQ$问题,这次是二维问题,好,那就上二维$ST$表,构造方法和一维的类似.开一个四维数组,第一维第三维管横行,第二维第四维管纵行即可(反过来也行).然后处理完之后按照类似于一维$ST$表一样查询,查询四个小矩阵的最值就行,然后取最值,具体看代码. AC代码:

Codeforces Round #371 (Div. 1) D - Animals and Puzzle 二维ST表 + 二分

D - Animals and Puzzle #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define ull unsigned long long using namespace std; const in

算法详解——st表

st表是解决区间RMQ(区间最值问题)的一类算法,时间复杂度为O(nlogn)的预处理和O(1)的查询,其主要运用了类似倍增的思想... 总体来说,st表的用处还是挺大的,代码也比较短,容易记... st表 若现在给定一个长度为n的序列A,每次给定两个数l,r,求出A[l]~A[r]中的最大值... 那么我们考虑怎么做,首先是朴素做法,每次询问最大值时用for循环从l到r跑一遍,每次循环复杂度为O(r - l) 那有没有一种算法可以让我们以O(1)的复杂度就知道最大值呢? 这时我们引进st表算法

二维 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&

PHP生成二维码的2种方式

伸展树模版真的好长好长... cut a b c:把第a-1个数伸展到根节点,把第b+1个数伸展到a的右子树,然后把ch[ch[root][1][0]]拿掉,放在剩下的树的第c个节点下. flip a b:把第a-1个数伸展到根节点,把第b+1个数伸展到a的右子树,然后翻转ch[ch[root][1][0]]: 由于会出现操作两边的情况,所以加了两个-1节点. 注意: 1,输出的时候要注意空格和换行. 2,在拿掉子树的时候要注意push_up(); #include<stdio.h> #inc

在web页面上快速生成二维码的两种实用方法

二维码是桌面和移动端快速分享的高效手段之一,这里介绍两个不错的快速开发二维码的方法,和大家分享一下~~ 方法1:使用新浪提供的服务 这种方式简单快速,在服务端生成一个二维码的图片,兼容性比较好,你无需自己处理任何相关二维码的生成,只需要提供一端文字或者url即可,方法如下: <img src="http://qrcoder.sinaapp.com?t=http://www.gbtags.com"> 生成效果如下: 大家扫一扫就可以访问极客标签主站了~~ 方法2: 使用jQu

【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA

传送门 写在前面:一天下来就写了两道主席树的题--(codevs上的一道智障天梯不算) 思路: 才知道原来主席树不仅可以通过dfs序维护子树区间,还可以直接维护一条到根的链-- 我们建好主席树后,每次查询u->v路径上的第k大,无非有两种情况 1.u,v在同一条链上 2.u,v不在同一条链上 其实这两种情况处理起来是一样的,我们利用主席树中的前缀和思路,root[u]并上root[v]再减去root[lca(u,v)]再减去root[fa[lca(u,v)]]就是u->v路径上的点了(可以自己

PHP生成带logo图像二维码的两种方法

本文主要和大家分享PHP生成带logo图像二维码的两种方法,主要以文字和代码的形式和大家分享,希望能帮助到大家. 一.利用Google API生成二维码Google提供了较为完善的二维码生成接口,调用API接口很简单,以下是调用代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $urlToEncode="http://www.php.cn"; generateQRfromGoogle($urlToEncode); /**

使用PHP生成二维码的两种方法(带logo图像)

一.利用Google API生成二维码 Google提供了较为完善的二维码生成接口,调用API接口很简单,以下是调用代码: $urlToEncode="http://www.jb51.net"; generateQRfromGoogle($urlToEncode); /** * google api 二维码生成[QRcode可以存储最多4296个字母数字类型的任意文本,具体可以查看二维码数据格式] * @param string $chl 二维码包含的信息,可以是数字.字符.二进制信息