uva 11235 - Frequent values

来源:互联网 发布:mac 桌面壁纸位置 编辑:程序博客网 时间:2024/05/17 03:59
2007/2008 ACM International Collegiate Programming Contest 
University of Ulm Local Contest

Problem F: Frequent values

You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.


题意:给出一个非递减的序列,找出某个区间出现次数最多的数的个数。


题目思路: RMQ + 边界的处理


解题方法:把序列分成t段(t等于序列不同数值的数个数),每段表示这个数出现的次数,例如tot[1]表示第一个数的个数,然后这个数组相当于RMQ的a数组。同时输入的时候需要记录每个数出现的左边界值numL[i]和右边界值numR[i]。最后只需要将区间划分为三段进行处理:1:numR[num[l]]-l+1(假如左边界的数是解);

      2:r-numL[num[r]]+1(假如右边界的数是解);

      3:RMQ(num[l]+1,num[r]-1) (解在区间的中间段);

特殊情况:如果左边界和右边界属于同一段,也就是说是同一个数,那么结果就直接求得:r-l+1;


代码如下:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>using namespace std;#define N 100010int mm[N][30],num[N],numL[N],numR[N],tot[N];void RMQ_DP(int n){    for(int i=1;i<=n;i++)        mm[i][0]=tot[i];    int nj=log(n+0.0)/log(2.0);    for(int j=1;j<=nj;j++){        int ni=n-(1<<j)+1;        for(int i=1;i<=ni;i++){            mm[i][j]=max(mm[i][j-1],mm[i+(1<<(j-1))][j-1]);           // mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);        }    }}int RMQ(int l,int r){    if(l>r) return 0;    int k=log(r-l+1.0)/log(2.0);    int Mm = max(mm[l][k],mm[r-(1<<k)+1][k]);   // int Mi = min(mi[l][k],mi[r-(1<<k)+1][k]);    return Mm;}int main(){    int n,q;    while(scanf("%d",&n)!=EOF){        if(n==0) break;        scanf("%d",&q);        memset(tot,0,sizeof(tot));       // memset(numL,0,sizeof(numL));       // memset(numR,0,sizeof(numR));        int c,t=0,tmp;        for(int i=1;i<=n;i++){            scanf("%d",&c);            if(i==1){                ++t;                numL[t]=1;                numR[t]=0;                tmp = c;            }            if(c==tmp){                num[i]=t;                tot[t]++;                numR[t]++;            }else{                num[i]=++t;                tot[t]++;                numL[t]=numR[t]=i;                tmp=c;            }        }        RMQ_DP(t);        while(q--){            int l,r;            scanf("%d%d",&l,&r);            if(num[l]==num[r]){                 printf("%d\n",r-l+1);                 continue;            }            int ans=max( max(numR[num[l]]-l+1,r-numL[num[r]]+1),RMQ(num[l]+1,num[r]-1) );            printf("%d\n",ans);        }    }    return 0;}



0 0