zoukankan      html  css  js  c++  java
  • rmq_ST算法(矩阵最值)

    已知某矩阵中的值已经确定,需求矩阵中某个小矩阵的最值

    ST算法

    我们可以将每一行看作一维的rmq

     maxx[i][j][k]表示: 第i行 [j,j+(1<<k)-1] 区间中的最大值
        maxx[i][j][k]=max(maxx[i][j][k-1],maxx[i][j+(1<<(k-1))][k-1]);
        该时间复杂度为:
            建表:0(n*m*log(m))
            查询:0(n)

    模板:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    const int N=1e3+7;
    const int inf=1e9+7;
    int n,m;
    int maxx[N][N][13],minn[N][N][13];
    int Log2[N];
    void ST()
    {
        for(int i = 0; i <= m; i ++)Log2[i] = (i == 0 ? -1 : Log2[i >> 1] + 1);
        for(int i=1;i<=n;i++)
            for(int k=1;k<13;k++)
                for(int j=1;j+(1<<k)<=m+1;j++)
                {
                    maxx[i][j][k]=max(maxx[i][j][k-1],maxx[i][j+(1<<(k-1))][k-1]);
                    minn[i][j][k]=min(minn[i][j][k-1],minn[i][j+(1<<(k-1))][k-1]);
                }
    }
    int query_min(int lx,int ly,int rx,int ry)
    {
        int k=Log2[ry-ly+1];
        int minn1=inf;
        for(int i=lx;i<=rx;i++)
            minn1=min(minn1,min(minn[i][ly][k],minn[i][ry-(1<<k)+1][k]));
        return minn1;
    }
    int query_max(int lx,int ly,int rx,int ry)
    {
        int k=Log2[ry-ly+1];
        int maxx1=-inf;
        for(int i=lx;i<=rx;i++)
            maxx1=max(maxx1,max(maxx[i][ly][k],maxx[i][ry-(1<<k)+1][k]));
        return maxx1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&maxx[i][j][0]);
                minn[i][j][0]=maxx[i][j][0];
            }
        ST();
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int lx,ly,rx,ry;
            scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
            printf("%d %d
    ",query_max(lx,ly,rx,ry),query_min(lx,ly,rx,ry));
        }
        return 0;
    }

    poj 2019 Cornfields

    二维rmq模板题:

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    const int N=250+7;
    const int inf=15625000+7;
    int n,minn[N][N][10],maxx[N][N][10],Log2[N];
    void ST()
    {
        for(int i=0;i<=n;i++) Log2[i]=(i==0?-1:Log2[i>>1]+1);
        for(int i=1;i<=n;i++)
            for(int k=1;k<10;k++)
                for(int j=1;j+(1<<k)<=n+1;j++)
                {
                    minn[i][j][k]=min(minn[i][j][k-1],minn[i][j+(1<<(k-1))][k-1]);
                    maxx[i][j][k]=max(maxx[i][j][k-1],maxx[i][j+(1<<(k-1))][k-1]);
                }
    }
    int query_min(int lx,int ly,int rx,int ry)
    {
        int minn1=inf;
        int k=Log2[ry-ly+1];
        for(int i=lx;i<=rx;i++)
            minn1=min(minn1,min(minn[i][ly][k],minn[i][ry-(1<<k)+1][k]));
        return minn1;
    }
    int query_max(int lx,int ly,int rx,int ry)
    {
        int maxx1=-inf;
        int k=Log2[ry-ly+1];
        for(int i=lx;i<=rx;i++)
            maxx1=max(maxx1,max(maxx[i][ly][k],maxx[i][ry-(1<<k)+1][k]));
        return maxx1;
    }
    int main()
    {
        int b,k;
        scanf("%d%d%d",&n,&b,&k);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&minn[i][j][0]);
                maxx[i][j][0]=minn[i][j][0];
            }
        ST();
        while(k--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",query_max(x,y,x+b-1,y+b-1)-query_min(x,y,x+b-1,y+b-1));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    可重入函数
    进程间通信的方法和实现
    Qt之Qprocess
    mysql学习(十二)内置函数
    mysql学习(十一)嵌套查询 排序 分组
    mysql学习(十)多表查询
    ubuntu 12.04 安装谷歌浏览器
    mysql学习(九)sql语句
    mysql学习(八)数据表类型-字符集
    mysql远程连接问题-http://www.cnblogs.com/jerome-rong/archive/2013/03/05/2944264.html
  • 原文地址:https://www.cnblogs.com/lemon-jade/p/8392911.html
Copyright © 2011-2022 走看看