zoukankan      html  css  js  c++  java
  • 算法学习

    2017-08-26 21:44:45

    writer:pprp

    RMQ问题就是区间最大最小值查询问题;

    这个SparseTable算法构造一个表,F[i][j] 表示 区间[i, i + 2 ^ j -1]的最大或者最小值

    ST分为两个部分

    1、nlogn的预处理

    预处理主要用到了动态规划,二分区间每个区间长度为 2 ^ (j -1)找到一个递推关系;

    F[i][j] = min(F[i][j - 1],F[i + (1 << (j - 1))][j - 1]);

    2、查询部分更为巧O(1)得到询问结果

    对于任意一个区间【n,m】来说,可以将其划分为两个以上区间的和

    【m,n】 = 【m, m+2^k-1】 + 【n-2^k-1,n】

    其中k = log2(n-m+1)

    实现的代码如下:

    /*
    @theme:ST表(sparse table)稀疏表
    @writer:pprp
    @declare:用动态规划的思想来解决RMQ问题;
    @date:2017/8/26
    */
    
    /*方程
    F[i,j]:区间[i,i + 2^j - 1]的最小值,此时区间长度为2^j
    转移方程:F[i,j] = min(F[i,j - 1],F[i + 2^(j - 1),j - 1])
    初始化:F[i,0] = nArr[i];
    */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    int F[1000000][20];//待比较元素的个数最大为1百万
    
    void SparseTable(int a[], int len)
    {
        //初始化
        for(int i = 0 ; i < len ; i++)
            F[i][0] = a[i];
        //递推
        //找到j的范围log2(n)
        int nlog = int(log(double(len))/log(2.0));
        for(int j = 1 ; j <= nlog; j++)
        {
            for(int i = 0 ; i < len ; i++)
            {
                //区间右端点不能超过数组最后一位下标
                if((i + (1 << j) -1) < len )
                {
                    F[i][j] = min(F[i][j - 1],F[i + (1 << (j - 1))][j - 1]);
                }
            }
        }
    }
    
    int RMQ(int a[], int len, int Start, int End)
    {
        //中间变量的选取log2(len)
        int nlog = (int)(log(double(End-Start+1))/log(2.0));
    
        return min(F[Start][nlog], F[End - (1 << nlog) + 1][nlog]);
    }
    
    int main()
    {
        int a[] = {2,34,2,3,23,2,23,1,23,123,23,232,3,25,565,76};
    
        for(int i = 0 ; i < 16 ; i++)
        {
            cout << a[i] <<" ";
        }
        cout << endl;
    
        SparseTable(a,16);
        int l, r;
        while(cin >> l >> r)
        {
            cout << RMQ(a,16,l,r) << endl;
        }
        return 0;
    }

     ST模板

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int F[1000000][20];
    void ST(int a[],int len)
    {
        for(int i = 0 ; i < len ; i++)
            F[i][0] = a[i];
        int nlog = int(log(double(len))/log(2.0));
        for(int j = 1; j <= nlog; j++)
        {
            for(int i = 0 ; i < len ; i++)
            {
                if(i+(1<<j)-1 < len)
                    F[i][j] = max(F[i][j-1],F[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int RMQ(int a[],int len, int l, int r)
    {
        int nlog = floor(log(double(r-l+1))/log(2.0));
        return max((F[l][nlog]),F[r-(1<<nlog)+1][nlog]);
    }
    
    int main()
    {
        int a[10000];
        int n;
        cin >> n;
        for(int i = 0 ; i < n ; i++)
            cin >> a[i];
        ST(a,n);
        int l,r;
        int cas;
        cin >> cas;
        while(cas--)
        {
            cin >> l >> r;
            cout << RMQ(a,n,l,r) << endl;
        }
    
        return 0;
    }
  • 相关阅读:
    前端--HTML
    并发函数--线程
    并发编程--进程
    一个好用的网站,各种在线
    django Models与数据库关系
    流文件下载
    小白都能秒懂的各数据库在Django的配置
    关于django 内建缓存 信号 及自定义json的配置
    django批量创建数据
    关于drf的组件
  • 原文地址:https://www.cnblogs.com/pprp/p/7436498.html
Copyright © 2011-2022 走看看