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;
    }
  • 相关阅读:
    缓存穿透与缓存雪崩
    hibernate 用hql做中文排序
    设计一个算法,求非空二叉树中指定的第k层(k&gt;1)的叶子节点的个数
    CI框架源代码阅读笔记3 全局函数Common.php
    Linux安装中文man手冊
    ios 自己定义导航栏和切割线
    算法7-7:有向图简单介绍
    [Leetcode]-Min Stack
    ios28--UIScrollView
    ios27--kvo
  • 原文地址:https://www.cnblogs.com/zeroform/p/7787962.html
Copyright © 2011-2022 走看看