Uva 11235 频繁出现的数值(RMQ-Sparse Table 算法)(训练指南)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2176

范围最小值问题(Range Minimum Query,RMQ).实践中最常用的是Sparse Table 算法,预处理时间是O(nlogn),查询只需要O(1),而且常数很小。

注意到整个数组是非降序的,所有相等元素会聚集到一起。这样可以把整个数组进行游程编码。比如-1,1,1,2,,2,2,4可以编码成(-1,1)(1,2),(2,3),(4,1),其中(a,b)表示有b个连续的a.



#include <cstdio>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=100000+5;
int a[maxn],l[maxn],r[maxn],num[maxn];
///num[p]表示位置p所在段的编号
///l[p],r[p]分别表示所在段左右端点的位置
int d[maxn][25];
//vector<int> count;
void RMQ_init(const vector<int>& A)
{
    int v=A.size();
    for(int i=1;i<v;i++)
            d[i][0]=A[i];
    for(int j=1;(1<<j)<=v;j++)
        for(int i=0;i+(1<<j)-1<v;i++)
            d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;///如果2^(k+1)<=R-L+1,那么k还可以加1
    return max(d[L][k],d[R-(1<<k)+1][k]);
}
int main()
{
    int q,n;
    while(~scanf("%d",&n)&&n!=0){
        scanf("%d",&q);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        a[n]=a[n-1]+1;
        int start=-1;
        vector<int> count;
        for(int i=0;i<=n;i++)
            if(i==0||a[i]>a[i-1]){
            if(i>0){
                count.push_back(i-start);
                for(int j=start;j<i;j++){
                    num[j]=count.size()-1,l[j]=start,r[j]=i-1;
                }
            }
            start=i;
        }
        RMQ_init(count);
        while(q--){
            int L,R,ans;
            scanf("%d%d",&L,&R);
            L--;R--;
            if(num[L]==num[R]) ans=R-L+1;
            else{
                ///最后结果是从L到L所在段结束的元素个数,
                ///从R所在段开始处到R处元素个数,
                ///中间第num[L]+1段到第num[R]-1段的count的最大值
                ans=max(r[L]-L+1,R-l[R]+1);
                if(num[L]+1<=num[R]-1) ans=max(ans,RMQ(num[L]+1,num[R]-1));
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}


你可能感兴趣的:(Uva 11235 频繁出现的数值(RMQ-Sparse Table 算法)(训练指南))