RMQ,ST表,dp

RMQ算法,

st表,dp思想

直接上代码吧,

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string>
 4 #include <bits/stdc++.h>
 5 
 6 using namespace std;
 7 typedef long long ll;
 8 typedef unsigned long long ull;
 9 
10 #define MAXN 100001
11 int stmax[MAXN][21];
12 int stmin[MAXN][21];
13 int a[MAXN];
14 int n,q;
15 
16 void rmq(int n) {
17     for (int j=1; j<20; j++) {
18         for (int i=1; i<=n; i++) {
19             if (i+(1<<j)-1<=n) {
20                 stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
21                 stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
22             }
23         }
24     }
25 }
26 int ask(int l,int r) {
27     int k=log(r-l+1)/log(2);
28     int maxans=max(stmax[l][k],stmax[r-(1<<k)+1][k]);
29     int minans=min(stmin[l][k],stmin[r-(1<<k)+1][k]);
30     cout<<maxans<<" "<<minans<<endl; 
31 }
32 
33 int main () {
34     cin>>n>>q;
35     for (int i=1;i<=n;i++) {
36         cin>>a[i];
37         stmax[i][0]=a[i];
38         stmin[i][0]=a[i];
39     }
40     rmq(n);
41     for (int i=1,l,r;i<=q;i++) {
42         cin>>l>>r;
43         ask(l,r);
44     }
45 
46     return 0;
47 }

RMQ还有扩展应用,

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cassert>

using namespace std;
typedef long long LL;
LL mod = 1e9+7;
LL cnt;
int s[100005],n,q;
int sta[100005][20],sto[100005][20];
int aska(int l,int r) {
    int L=r-l+1;
    int t = log2(L);
    return sta[l][t] & sta[r-(1<<t)+1][t];
    //对应区间最小
}
int asko(int l,int r) {
    int L=r-l+1;
    int t = log2(L);
    return sto[l][t] | sto[r-(1<<t)+1][t];
    //对应区间最大
}
int main() {
    scanf("%d%d",&n,&q);
    for(int i=1; i<=n; i++) {
        scanf("%d",&s[i]);
        sta[i][0]=sto[i][0]=s[i];
    }
    for(int j=1; j<20; j++) {
        for(int i=1; i<=n; i++) {
            if(i+(1<<j) -1 <=n) {
                sta[i][j] = sta[i][j-1] & sta[i+(1<<(j-1))][j-1];
                sto[i][j] = sto[i][j-1] | sto[i+(1<<(j-1))][j-1];
            }
        }
    }

    for(int i=1,l,r; i<=q; i++) {
        scanf("%d%d",&l,&r);
        cout<<aska(l,r)<<" "<<asko(l,r)<<endl;
    }


    return 0;
}

扩展之后RMQ可以求一个序列一段区间连续按位与,按位或的值

按位与对应区间最小值

按位或对应区间最大值

posted @ 2018-10-16 17:34  codemaker_li  阅读(120)  评论(0编辑  收藏  举报