RMQ算法题目

pku 3264 http://poj.org/problem?id=3264

题意:

给定n个奶牛的高度,求区间[s,e]中最高与最低高度的差值。

rmq模板题目:

求出最高最低然后求差。

注意这里f[i][j]表示从j开始的2^i次方个数的最值。

View Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define maxn 50007
#define N 22
using namespace std;

int fMin[N][maxn],fMax[N][maxn];
int pow2[N],a[maxn];

void init_rmq(int len)
{
    int i,j;
    for (i = 0; i < N; ++i) pow2[i] = 1<<i;

    for (i = 1; i <= len; ++i)
    fMin[0][i] = fMax[0][i] = a[i];

    for (i = 1; pow2[i] <= len; ++i)//pow2[i]表示长度一定小于总长度
    {
        for (j = 1; j + pow2[i - 1] <= len; ++j)//j + pow2[i - 1]表示右边的起点一定要小于最右边的坐标
        {
            fMax[i][j] = max(fMax[i - 1][j],fMax[i - 1][j + pow2[i - 1]]);
            fMin[i][j] = min(fMin[i - 1][j],fMin[i - 1][j + pow2[i - 1]]);
        }
    }
}

int rmq(int s,int e)
{
    int k = log(1.0*(e -s + 1))/log(2.0);
    int Max = max(fMax[k][s],fMax[k][e - pow2[k] +1]);
    int Min = min(fMin[k][s],fMin[k][e - pow2[k] +1]);
    return Max - Min;
}
int main()
{
    //freopen("d.txt","r",stdin);
    int n,q,i;
    int s,e;
    scanf("%d%d",&n,&q);
    for (i = 1; i <= n; ++i) scanf("%d",&a[i]);

    init_rmq(n);
    while (q--)
    {
        scanf("%d%d",&s,&e);
        printf("%d\n",rmq(s,e));
    }
    return 0;
}

 

 pku Frequent values http://poj.org/problem?id=3368

题意:

给定长度为n的不降序列,求询问区间[s,e]内出现频率最高的频率;

思路:

本题可用线段树的区间合并来做:http://www.cnblogs.com/E-star/archive/2012/07/26/2609475.html

rmq做法,首先将其离散化相同的点映射到一个点上,并记录该点能够达到的最左端点最有端点;

分三种情况讨论[s,e]

hash[i]位i离散化后对应的新序号,R[hash[i]]表示i离散化后的点能够到达的最右端,L[hash[i]]表示i离散化后的点能够到达的最左端,

1:如果s与e对应的离散化后的点为同一点则频率为 e - s + 1;(1,1,1,1)

2:如果s与e所对应的离散化后的点相差1则频率为 Li = R[hash[l]] - l + 1;   Ri = r - L[hash[r]] + 1; max(Li,Ri); (1 1 3 3)

3:如果s与e所对应的离散化后的点相差大于1则频率为

Li = R[hash[l]] - l + 1;
Ri = r - L[hash[r]] + 1;
Li = max(Li,Ri);
Ri = rmq(hash[l] + 1,hash[r] - 1);
max(Li,Ri);

View Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define maxn 100007
using namespace std;

int hash[maxn],L[maxn],R[maxn];
int a[maxn],f[maxn][22],pow2[22];

void init_rmq(int len)
{
    int i,j;
    for (i = 0; i < 22; ++i) pow2[i] = 1<<i;

    for (j = 1; pow2[j] <= len; ++j)
    {
        for (i = 1; i + pow2[j] <= len; ++i)
        f[i][j] = max(f[i][j - 1],f[i + pow2[j - 1]][j - 1]);
    }
}
int rmq(int s,int e)
{
    int k = log(1.0*(e - s + 1))/log(2.0);
    return max(f[s][k],f[e - pow2[k] + 1][k]);
}

void solve(int l,int r)
{
    int Li,Ri;
    if (hash[l] == hash[r])
    {
        printf("%d\n",r - l + 1);
    }
    else if (hash[l] + 1 == hash[r])
    {
        Li = R[hash[l]] - l + 1;
        Ri = r - L[hash[r]] + 1;
        printf("%d\n",max(Li,Ri));
    }
    else
    {
        Li = R[hash[l]] - l + 1;
        Ri = r - L[hash[r]] + 1;
        Li = max(Li,Ri);
        Ri = rmq(hash[l] + 1,hash[r] - 1);
        printf("%d\n",max(Li,Ri));
    }
}
int main()
{
    //freopen("d.txt","r",stdin);
    int n,q,i;
    while (~scanf("%d",&n))
    {
        if (!n) break;
        scanf("%d",&q);
        for (i = 1; i <= n; ++i) scanf("%d",&a[i]);
        hash[1] = 1;
        L[1] = 1;
        R[1] = 1;
        int cnt = 1;
        for (i = 2; i <= n; ++i)
        {
            if (a[i] == a[i - 1])
            {
                hash[i] = hash[i - 1];
                R[hash[i]] = i;
            }
            else
            {
                f[cnt][0] = R[cnt] - L[cnt] + 1;//直接对f初始化了。
                hash[i] = ++cnt;
                L[cnt] = i;
                R[cnt] = i;
            }
        }
        f[cnt][0] = R[cnt] - L[cnt] + 1;
        init_rmq(cnt);
        int s,e;
        while (q--)
        {
            scanf("%d%d",&s,&e);
            solve(s,e);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值