码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3368 Frequent values(一维RMQ)

时间:2015-08-17 19:11:22      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:

题意:求给定区间中出现最多的数的出现次数,原数列为非降序列;

思路:将原数列处理为当前数在连续数中的出现顺序;从后向前处理;

       对于查询区间[l,r],先通过二分计算与a[r]相同的数的个数(num[r]可能大于1);剩余区间rmq求最大值;在求两种情况的最大值;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int num[500010],mm[500010];
int dp[300010][30],a[500010];
void init_rmq(){
   mm[0]=-1;
   for(int i=1;i<=n;i++){
     mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1];//注意(i&(i-1))
     dp[i][0]=num[i];
   }
   for(int j=1;j<=mm[n];j++){
    for(int i=1;i+(1<<j)-1<=n;i++){
        dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); //注意(1<<(j-1))
    }
   }
}
int rmq(int x,int y){
    int k=mm[y-x+1];
    return max(dp[x][k],dp[y-(1<<k)+1][k]);
}
int bsearch(int s,int t){
    int ans=a[t];
    int l=s,r=t;
    while(l<r){
        int mid=(l+r)/2;
        if(a[mid]>=ans) r=mid;
        else l=mid+1;
    }
    return r;
}
int main(){
  int i,j,k,u,v;
  while(scanf("%d",&n)!=EOF){
    if(n==0) break;
    scanf("%d",&m);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    memset(num,0,sizeof(num));
    for(i=n;i>=1;i--){
        int temp;
        if(i==n) temp=1;
        else{
            if(a[i]==a[i+1]) temp++;
            else temp=1;
        }
        num[i]=temp;
    }
    init_rmq();
    for(i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        int temp=bsearch(u,v);
        int cnt=v-temp+1;
        int st=temp-1;
        if(st<u) printf("%d\n",cnt);
        else printf("%d\n",max(cnt,rmq(u,st)));
    }
  }
  return 0;
}

 

poj 3368 Frequent values(一维RMQ)

标签:

原文地址:http://www.cnblogs.com/dominatingdashuzhilin/p/4737337.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!