• 模板之st表


    题意:

    给出n个数字与q组询问,每次询问一个区间[l,r]的最小值与最大值。

    首先,此题可用线段树保存最大值和最小值。。。但是因为没有修改,所以用一些更简单的数据结构即可

    st表的功能:nlogn的时间预处理每个点为端点2^x长度的区间信息,然后就可以在O(1)的时间内完成询问。

    mn数组的意义在于保存区间的长度,stmin与stmax来保存最大值与最小值。

    每次以i为端点更新左右2^j长度的区间信息,注意先枚举j。

    比较以l为左端点与以r为右端点的区间信息,回答询问。

    #include<cstdio>
    int stmax[100005][20],stmin[100005][20];
    int a[100005],mn[100005];
    int t,q,n,l,r;
    int max(int x,int y)
    {
        if(x>y) return x;
        else return y;
    }
    int min(int x,int y)
    {
        if(x<y) return x;
        else return y;
    }
    int main()
    {
        scanf("%d",&n);scanf("%d",&q);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        mn[0]=-1;
        for(int i=1;i<=n;i++)
        {
            if((i&(i-1))==0) mn[i]=mn[i-1]+1;
            else mn[i]=mn[i-1];
            stmax[i][0]=a[i];
            stmin[i][0]=a[i];
        }
        for(int j=1;j<=mn[n];j++)
        {
            for(int i=1;i+(1<<j)<=n+1;i++)
            {
                stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<j-1)][j-1]);
                stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<j-1)][j-1]);
            }
        }
        while(q--)
        {
            scanf("%d %d",&l,&r);
            int k=mn[r-l+1];
            printf("%d ",min(stmin[l][k],stmin[r-(1<<k)+1][k]));
            printf("%d
    ",max(stmax[l][k],stmax[r-(1<<k)+1][k]));
        }
        return 0;
    }
  • 相关阅读:
    转:理想主义终结年代的七种兵器
    基础地理空间框架
    coldplay 全集下载
    S40 用google sync同步通讯录(转)
    分享一个关于Steve Jobs演讲的分析
    转:我们时代的思想责任与尊严
    nginx 视频流
    vue 使用路由重复跳转同一页面
    批处理文件编写
    ZBB – ZERO Bug Bounce
  • 原文地址:https://www.cnblogs.com/zeroform/p/7787962.html
Copyright © 2020-2023  润新知