uva11235 RMQ

来源:互联网 发布:什么是数据挖掘 编辑:程序博客网 时间:2024/04/26 00:18

一段不减序列a1,a2...an,对于任意询问(i,j),回答ai,a(i+1)...aj中出现次数最多的值所出现的次数

按照不同值将序列分为若干段,记录相关数组,并用RMQ进行询问。

#include<cstdio>#include<algorithm>#include<vector>using namespace std;const int maxn=100000+10;const int maxlog=20;//区间最大值struct RMQ{    int d[maxn][maxlog];    void init(const vector<int>& A){        int n=A.size();        for(int i=0;i<n;i++) d[i][0]=A[i];        for(int j=1;(1<<j)<=n;j++)            for(int i=0;i+(1<<j)-1<n;i++)                d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);    }    int query(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]);    }};//a[i]:第i个数的值,num[i]:第i个数的编号,left[i]、right[i]:第i个数所在段的左右端点编号int a[maxn],num[maxn],left[maxn],right[maxn];RMQ rmq;int main(){    int n,q;    //freopen("a.txt","r",stdin);    while(scanf("%d",&n)!=EOF){        if(!n) break; 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,left[j]=start,right[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 {                ans=max(R-left[R]+1,right[L]-L+1);                if(num[L]+1<num[R]) ans=max(ans,rmq.query(num[L]+1,num[R]-1));            }            printf("%d\n",ans);        }    }    return 0;}


0 0
原创粉丝点击