• Evanyou Blog 彩带


    RMQ

      RMQ(Range Maximum/Minimum Question)是指区间最值问题,在OI中较为常见,一般可以用ST表和线段树实现。

      ST表是基于倍增思想的一种打表方法,在确定区间范围和所有的值后利用倍增预处理出$2^k$长度的区间内的最值,然后$O(1)$查询。优点是查询快且操作简便,缺点是不能进行动态操作,只支持静态查询。

      Code:(POJ模板题

    //It is made by HolseLee on 23rd July 2018
    //POJ 3264
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<iomanip>
    using namespace std;
    const int N=5e4+7;
    int n,m,a[N];
    int mx[N][25],mi[N][25];
    inline int read()
    {
      char ch=getchar();int num=0;bool flag=false;
      while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
      while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
      return flag?-num:num;
    }
    void ready()
    {
      for(int j=1;j<=21;j++)
        for(int i=1;i<=n;i++)
          if(i+(1<<(j-1))<=n){
        mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
        mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);}
    }
    inline int quary(int l,int r)
    {
      int maxx=-1,minn=998244353;
      int k=(int)(log((double)(r-l+1))/log(2.0));
      maxx=max(mx[l][k],mx[r-(1<<k)+1][k]);
      minn=min(mi[l][k],mi[r-(1<<k)+1][k]);
      return maxx-minn;
    }
    int main()
    {
      n=read();m=read();
      memset(mx,-1,sizeof(mx));
      memset(mi,0x7f,sizeof(mi));
      for(int i=1;i<=n;i++){
        a[i]=read();
        mi[i][0]=mx[i][0]=a[i];}
      ready();int x,y;
      for(int i=1;i<=m;i++){
        x=read();y=read();
        printf("%d
    ",quary(x,y));}
      return 0;
    }

      线段树就不用多说了,除了可以同时维护最大和最小值意外,还能维护更多信息,操作同样也方便,而且还支持动态操作。

      Code:

    //It is made by HolseLee on 23rd July 2018
    //POJ 3264
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<iomanip>
    using namespace std;
    const int N=5e4+7;
    int n,m,a[N];
    struct Node{
        int mx,mi;
        Node(int xx=0,int yy=0)
        {mx=xx;mi=yy;}
    }seg[N<<4];
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num; 
    }
    inline void update(int rt)
    {
        seg[rt].mx=max(seg[rt<<1].mx,seg[rt<<1|1].mx);
        seg[rt].mi=min(seg[rt<<1].mi,seg[rt<<1|1].mi);
    }
    inline void build(int l,int r,int rt)
    {
        if(l>r)return;
        if(l==r){
            seg[rt].mx=seg[rt].mi=a[l];return;}
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);
        update(rt);
    }
    inline Node quary(int l,int r,int rt,int L,int R)
    {
        Node ret(-1,998244353);
        if(l>R||r<L)return ret;
        if(L<=l&&r<=R){return seg[rt];}
        int mid=(l+r)>>1;
        Node lc(-1,998244353);
        Node rc(-1,998244353);
        if(L<=mid)lc=quary(l,mid,rt<<1,L,R);
        if(R>mid)rc=quary(mid+1,r,rt<<1|1,L,R);
        ret.mx=max(lc.mx,rc.mx);
        ret.mi=min(lc.mi,rc.mi);
        return ret;
    }
    inline int get(int x,int y)
    {
        int maxx=quary(1,n,1,x,y).mx;
        int minn=quary(1,n,1,x,y).mi;
        return maxx-minn;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
        a[i]=read();
        build(1,n,1);int x,y;
        for(int i=1;i<=m;i++){
            x=read();y=read();
            printf("%d
    ",get(x,y));}
        return 0;
    } 
  • 相关阅读:
    Oracle Words Spelling Error
    原创 分布式锁与应用场景
    原创 分布式事务简单实现思路
    原创 使用redis位图实现布隆过滤器
    原创 redis实现接口限流
    原创 jwt-security简单实现
    原创 抢购秒杀之redis高性能实现
    原创 springcloud feign优化配置
    原创 派单、抢单业务简单实现
    原创 微信公众号推送图片实现
  • 原文地址:https://www.cnblogs.com/cytus/p/9356413.html
Copyright © 2020-2023  润新知