• 关于st表的推导


    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn=1e6+7;
    int st[maxn][32];
    int a[maxn],n;
    void init(){
        int i,j;
        //st[i][j]表示i到i+2^j-1区间的最小值
        //先预处理区间长度为1的
        for(i=0;i<n;++i)  st[i][0]=a[i];
        for(i=0;i<n;++i){
            for(j=1;i+2^(j)-1<n;++j){
                //i~i+2^(j-1)-1
                //i+2^(j-1)~i+2^(j-1)+2^(j-1)-1=>i+2^j-1;
                //一定要发现这个显然的事实就是
                //2^(j-1)+2^(j-1)=2^j; 
                st[i][j]=min(s[i][j-1],s[i+2^(j-1)][j-1]);
            }
        }
    }
    int queryMin(int l,int r){
        int len=r-1+1;
        int index=log(len);
        //st[l][index] l~l+2^(index)-1
        //2^(index)<=(r-l+1); l+2^(index)-1<=r
        //r-(l+2^(index)-1)>=0 还差多少元素没放进来
        //x+LEN=l+2^(index)-1+(r-(l+2^(index)-1));
        //x+2^(index)-1=r;//区间长度固定。。起点是多少才能正好跑到r,列一个简单的方程才能解决 
        //x=r+1-(2^(index));
        return min(st[l][index],st[r+1-(2^(index))][index]);
    }
    int main(){
        while(~scanf("%d",&n)){
            int i,q,l,r;
            for(i=0;i<n;++i){
                scanf("%d",a+i);
            }
            init();
            scanf("%d",&q);
            for(i=0;i<q;++i){
                scanf("%d%d",&l,&r);
                printf("%d
    ",query(l,r));
            }
        }
        return 0;
    }

    上面这个^符号代表幂次。。而c++里只有异或。。这就是为什么这是一个伪代码的意思

    先来一个终极伪代码

    推导过程如上。。

    下面给一个真正的的代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn=1e6+7;
    int st[maxn][32];
    int a[maxn],n;
    void init(){
        int i,j;
        //st[i][j]表示i到i+2^j-1区间的最小值
        //先预处理区间长度为1的
        for(i=0;i<n;++i)  st[i][0]=a[i];
        for(i=0;i<n;++i){
            for(j=1;i+(1<<j)-1<n;++j){//这里有一个优化。。本来是小于32的。。问题规模较小是只是相当于一个常数的优化 
                //i~i+2^(j-1)-1
                //i+2^(j-1)~i+2^(j-1)+2^(j-1)-1=>i+2^j-1;
                //一定要发现这个显然的事实就是
                //2^(j-1)+2^(j-1)=2^j; 
                st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int queryMin(int l,int r){
        int k=log(r-l+1);
        //st[l][index] l~l+2^(index)-1
        //2^(index)<=(r-l+1); l+2^(index)-1<=r
        //r-(l+2^(index)-1)>=0 还差多少元素没放进来
        //x+LEN=l+2^(index)-1+(r-(l+2^(index)-1));
        //x+2^(index)-1=r;//区间长度固定。。起点是多少才能正好跑到r,列一个简单的方程才能解决 
        //x=r+1-(2^(index));
        return min(st[l][k],st[r+1-(1<<k)][k]);
    }
    int main(){
        while(~scanf("%d",&n)){
            int i,q,l,r;
            for(i=0;i<n;++i){
                scanf("%d",a+i);
            }
            init();
            scanf("%d",&q);
            for(i=0;i<q;++i){
                scanf("%d%d",&l,&r);
                printf("%d
    ",queryMin(l-1,r-1));
            }
        }
        return 0;
    }

    还有一个对于新手来说理解的坑。。那就是int x=log(val)实际上是对log的值向下取整。。这一点非常重要
    只有这个成立我们注释里的推导才会成立。。另外有一些没用的推导。。但是我没有删掉。。这是因为想记录一下我全部的思考过程

  • 相关阅读:
    Leetcode:linked_list_cycle
    关于Go语言共享内存操作的小实例
    程序猿如同妓女
    算法——排序算法个人总结
    CentOS 6.4下安装和配置Samba 第2页_服务器应用_Linux公社-Linux系统门户网站
    解决fedora samba在windows下无权限访问的问题
    基于samba实现win7与linux之间共享文件_阳仔_新浪博客
    增加samba用户提示Failed to add entry for user
    Ubuntu+Win7+Samba实现文件共享_Linux教程_Linux公社-Linux系统门户网站
    Mycat 月分片方法
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6347769.html
Copyright © 2020-2023  润新知