RMQ问题

st表预处理,时间复杂度nlogN,适用于n较小,一般在1e5级别,查询m非常的情况下,很适合用st表预处理,然后查询区间最值,先把模板给出来。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m, a[N];
struct rmp
{
    int f[N][50], lg[N] = {-1};
    void init()
    {
        for(int i = 1; i <= n; ++i) f[i][0] = a[i];
        for(int i = 1; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
        for(int j = 1; j <= lg[n]; ++j)
            for(int i = 1; i + (1 << j) - 1 <= n; ++i)
                f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    }
    int query(int x, int y)
    {
        int s = lg[y - x + 1];
        return max(f[x][s], f[y - (1 << s) + 1][s]);
    }
}st;
signed main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    st.init();
    int l, r;
    while(m-- && scanf("%d%d", &l, &r))
    {
        printf("%d\n", st.query(l, r));
    }
    return 0;
}

Frequent values(st表)

传送门

既然是连续的,相同的值连在一起,预处理每个值出现了多少次,然后st表处理,然后分块的思想去搞

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 100;
int n, q;
int a[N], b[N], L[N], R[N], cnt, pos[N];
int f[N][50], clg[N] = {-1};
void init(int len)
{
    for(int i = 1; i <= len; ++i) f[i][0] = b[i];
    for(int i = 1; i <= len; ++i) clg[i] = clg[i >> 1] + 1;
    for(int j = 1; j <= clg[len]; ++j)
        for(int i = 1; i + (1 << j) - 1 <= len; ++i)
            f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
int query(int x, int y)
{
    if(x > y) return 0;
    int s = clg[y - x + 1];
    return max(f[x][s], f[y - (1 << s) + 1][s]);
}

signed main()
{
    while(scanf("%d", & n) && n)
    {
        scanf("%d", &q);
        memset(b, 0, sizeof b);
        a[0] = 1e6 + 1;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            pos[i] = (a[i] == a[i - 1] ? cnt : ++cnt);
            b[cnt]++;
            if(a[i] == a[i - 1]) L[i] = L[i - 1];
            else L[i] = i;
        }
        R[n] = n;
        for(int i = n - 1; i >= 0; --i)
        {
            if(a[i] == a[i + 1]) R[i] = R[i + 1];
            else R[i] = i;
        }
        init(cnt);
        int l, r;
        while(q-- && scanf("%d%d", &l, &r))
        {
            if(pos[l] == pos[r]) printf("%d\n", r - l + 1);
            else
            {
                int x = R[l] - l + 1;
                int y = r - L[r] + 1;
                int z = query(pos[l] + 1, pos[r] - 1);
                printf("%d\n", max(max(x, y), z));
            }
        }
    }
    return 0;
}

posted @ 2022-07-08 09:25  std&ice  阅读(100)  评论(0)    收藏  举报