ST表

用ST表求静态区间最大值

ST表不支持修改,预处理时间为nlog(n),但查询时间为O(1)

线段树支持修改,预处理时间为nlog(n),但查询时间是log(n)


模板例题


ST详解:

用f[i][j]表示区间 j~j+2^i-1 的最大值(即从j开始,向后2^i次这个区间中的最值)

预处理出bin[i]表示2^i,log[i]就表示log2(i)

#include<bits/stdc++.h>
    #define N 200010
    using namespace std;
    namespace program{
        long long bin[30],log[N],a[N];
        long long n,m,l,r,f[30][N];
        template<class T>
        T read(){
            T s=0;
            int ch;
            while(!isdigit(ch=getchar()));
            do
                s=s*10+(ch^48);
            while(isdigit(ch=getchar()));
            return s;
        }
        inline void init(){
            bin[0]=1;//2^0=1
            for(int i=1;i<=20;i++)    
                bin[i]=bin[i-1]*2;//bin[i]是2^i
            log[0]=-1;
            for(int i=1;i<=100010;i++)
                log[i]=log[i/2]+1;//比方说:log(2(32))=5=log(2(16))+1
            for(int i=1;i<=n;i++)
                f[0][i]=a[i];//预处理:从i开始只有一个那么无论最大最小都是它本身
        }
        inline void work(){
            n=read<long long>();//n是数组长度
            m=read<long long>();//m是询问次数
            for(int i=1;i<=n;i++)
                a[i]=read<long long>();
            init();
            for(int i=1;i<=log[n];i++)
                for(int j=1;j<=n;j++)
                    if(j+bin[i]-1<=n)    

                        f[i][j]=max(f[i-1][j],f[i-1][j+bin[i-1]]);

    //i-1很巧妙的吧f[i][j]这段区间分成了大小相同的两段,头指针分别为j和j+bin[i-1]
            while(m--){
                l=read<long long>();
                r=read<long long>();
                long long oo=log[r-l+1];           

                     cout<<max(f[oo][l],f[oo][r-bin[oo]+1])<<'\n';

    //和上面很像,然而要稍微反一下要先求出log(2,(r-l+1))
            }
        }
    }
    int main(){
        program::work();
        return 0;
    }

阅读更多
换一批

没有更多推荐了,返回首页