zoukankan      html  css  js  c++  java
  • 模板之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;
    }
  • 相关阅读:
    POJ3040--Allowance(贪心)
    Deep work
    湾区公司上班第一周
    三个现场面试
    协商薪资
    调节情绪,精神愉悦,健康快乐
    Phone interview guide 多说
    Campus Bikes
    降低软件复杂度 和 写注释写总结 2019-10
    某厂在线测试 2019.09.26
  • 原文地址:https://www.cnblogs.com/zeroform/p/7787962.html
Copyright © 2011-2022 走看看