简单的RMQ(RMQ+ST NEUQ“图灵杯”)

来源:互联网 发布:建设银行软件下载 编辑:程序博客网 时间:2024/06/12 18:47


问题 E: 简单的RMQ

时间限制: 2 Sec  内存限制: 64 MB
提交: 1012  解决: 190
[提交][状态][讨论版]

题目描述

给定一个数组,其中的元素满足非递减顺序。任意给定一个区间[i,j],求其中某个元素重复出现的最大次数。

输入

多组数据输入。每组数据的第一行包含两个整数n和q(1<=n,q<=100000),下一行包含n个整数a1,...,an(-100000<=ai<=100000,i∈{1,...,n}),用空格分隔,数列是升序的(ai<=ai+1)。接下来的q行,每行包含两个整数i和j(1<=i<=j<=n),表示给定区间[i,j]。
输入结束于0(自成一行)。

输出

对输入的q个区间,每个区间输出一个整数表示该区间内重复最多的元素出现的次数,用换行分隔。

样例输入

10 3-1 -1 1 1 1 1 3 10 10 102 31 105 100

样例输出

143

#include<cstdio>#include<iostream>#include<cmath>#include<algorithm>#define MAX 100005using namespace std;int stTable[MAX][20];int num[MAX];int sum[MAX];int n,q,ans,a,b;void Build_ST(){    for(int i=1;i<=n;i++)        stTable[i][0]=sum[i];    int k=log((double)(n+1))/log(2.0);    for(int i=1;i<=k;i++)      for(int j=1;j+(1<<i)<=n+1;j++)        stTable[j][i]=max(stTable[j][i-1],stTable[j+(1<<(i-1))][i-1]);    }int RMQ_Query(int l,int r){    if(l>r)return 0;    int k=log((double)(r-l+1))/log(2.0);    return max(stTable[l][k],stTable[r-(1<<k)+1][k]);}int main(){    while(scanf("%d",&n)!=EOF,n)    {        sum[1]=1;        scanf("%d",&q);        for(int i=1;i<=n;i++)        {            scanf("%d",&num[i]);            if(i==1)continue;            if(num[i]==num[i-1])sum[i]=sum[i-1]+1;            else sum[i]=1;        }        Build_ST();        while(q--){            scanf("%d%d",&a,&b);            if(a==b||num[a]==num[b]){                cout<<b-a+1<<endl;                continue;            }            int t=a;            while(num[t]==num[t-1]&&t<=b)                t++;            int cnt=RMQ_Query(t,b);            ans=max(cnt,t-a);            printf("%d\n",ans);        }    }    return 0;}/**************************************************************    Problem: 1760    User: T227    Language: C++    Result: 正确    Time:1488 ms    Memory:10136 kb****************************************************************/