UVA 11235 Frequent values(RMQ)

本文介绍了一种针对非递减排序列的查询优化算法。通过使用value和count数组去除重复元素,并采用RMQ(区间最大值查询)预处理技术来高效解决区间查询问题。文章详细展示了算法的具体实现过程及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为是非递减的,所以相同的是连在一起的。

那么只要用用两个数组value[i],count[i]把连续的去掉,value放的是不同的数组元素,count放的是该数的数量,用num[p],left[p],right[p],分别记录当前位置在去重后的位置,该段的左端点,右端点。

如果l,r在同一段里那么就是r-l+1,否则max(RMQ(num[l]+1,num[r]-1),max(right[l]-l+1,r-left[r]+1));

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define ss(x) scanf("%d",&x)
const int maxn=100000+5;
int d[maxn][17],value[maxn],Count[maxn],num[maxn],Left[maxn],Right[maxn],a[maxn];
int n,q;
int cnt;
void RMQ_intial()
{
    rep(i,1,cnt) d[i][0]=Count[i];
    for(int j=1;(1<<j)<=cnt;j++){
        for(int i=1;i+(1<<j)-1<=cnt;i++)
        {
            d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
        }
    }
}
int RMQ(int l,int r)
{
    if(r<l) return 0;
    int k=0;
    while((1<<(k+1))<=r-l+1) k++;
    return max(d[l][k],d[r-(1<<k)+1][k]);
}
int main()
{
    while(true)
    {
        ss(n);if(n==0) break;ss(q);
        rep(i,1,n) ss(a[i]);
        cnt=0;
        value[++cnt]=a[1];Count[cnt]=1;num[1]=1;Left[1]=1;Right[1]=1;
        rep(i,2,n){
            if(a[i]!=a[i-1]){
                rep(j,Left[i-1],Left[i-1]+Count[cnt]-1) Right[j]=Left[i-1]+Count[cnt]-1;
                value[++cnt]=a[i];Count[cnt]=1;num[i]=cnt;Left[i]=i;
            }
            else{
                Count[cnt]++;num[i]=cnt;Left[i]=Left[i-1];
            }
        }
        rep(j,Left[n],Left[n]+Count[cnt]-1) Right[j]=Left[n]+Count[cnt]-1;
        RMQ_intial();
        int l,r;
        rep(i,1,q)
        {
            ss(l);ss(r);
            if(num[l]==num[r]) printf("%d\n",r-l+1);
            else{
                printf("%d\n",max(RMQ(num[l]+1,num[r]-1),max(Right[l]-l+1,r-Left[r]+1)));
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值