poj3368--Frequent values--不递减数列的区间众数--RMQ问题
Posted BK-Edwina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3368--Frequent values--不递减数列的区间众数--RMQ问题相关的知识,希望对你有一定的参考价值。
Description
给一个不递减的长度为n的数列,q个询问,每次询问[l,r]区间内众数出现的次数。
Sample Input
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0
Sample Output
1
4
3
题解:
因为是有了不递减的限制,所以可以当成rmq问题来解决,还是用st算法。
st[i][0]要记录出现次数,额外需要加一个关于断点前后各自的众数的大小的判断。因为数列不递减,(使断点和断点后一个数不相等,即在当前情况下尽可能使断点靠后)所以如果断点后出现的次数,比断点前的多,那么更新ans(取两者max)
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 using namespace std; 6 const int maxn=100009; 7 int a[maxn],st[maxn][20],n,q; 8 int sum[maxn],l,r; 9 void init_st() 10 { 11 for(int i=n;i>=1;i--) 12 { 13 st[i][0]=sum[i]; 14 for(int j=1;(i+(1<<j)-1)<=n;j++) 15 { 16 st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]); 17 } 18 } 19 } 20 int ask(int l,int r) 21 { 22 if(l>r)return 0; 23 int k=((int)(log(r-l+1.0)/log(2.0))); 24 return max(st[l][k],st[r-(1<<k)+1][k]); 25 } 26 int main() 27 { 28 while(scanf("%d",&n)!=EOF) 29 { 30 if(n==0)break; 31 scanf("%d",&q); 32 for(int i=1;i<=n;i++) 33 { 34 scanf("%d",&a[i]); 35 if(i==1) 36 { 37 sum[i]=1; 38 continue; 39 } 40 if(a[i]==a[i-1]) 41 sum[i]=sum[i-1]+1; 42 else 43 sum[i]=1; 44 } 45 init_st(); 46 while(q--) 47 { 48 scanf("%d%d",&l,&r); 49 int tmp=l; 50 while(a[tmp]==a[tmp-1]&&tmp<=r) tmp++; 51 int cnt=ask(tmp,r); 52 int ans=max(cnt,tmp-l); 53 printf("%d\n",ans); 54 } 55 } 56 return 0; 57 }
以上是关于poj3368--Frequent values--不递减数列的区间众数--RMQ问题的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3368 Frequent values(线段树区间合并)
POJ3368Frequent values[RMQ 游程编码]