标签:
题意:求给定区间中出现最多的数的出现次数,原数列为非降序列;
思路:将原数列处理为当前数在连续数中的出现顺序;从后向前处理;
对于查询区间[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