Frequent values
Description
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.
Input
The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the
query.
The last test case is followed by a line containing a single 0.(多组数据)
Output
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
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要简单一点)或者RMQ算最大值。
具体代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #define N 100005 5 using namespace std; 6 int a[N],lo[N],pos[N]; 7 int n,m,x,y; 8 struct ii 9 { 10 int sta,end; 11 int num; 12 }aa[N]; 13 int f[N][20]; 14 int main() 15 { 16 freopen("poj3246.in","r",stdin); 17 freopen("poj3246.out","w",stdout); 18 //RQM 初始化,把log2(i),先打表出来 19 //f[][]是以连续区间个数,不是n个 20 while((scanf("%d%d",&n,&m))==2) 21 { 22 int i=1,q=2,p=0; 23 lo[i]=0; 24 while(i<=n) 25 { 26 i++; 27 if(i==q) 28 { 29 q*=2; 30 p++; 31 } 32 lo[i]=p; 33 } 34 int pre=N; 35 int k=0; 36 for(int i=1;i<=n;i++)//aa记录连续区间的起点中点个数 37 { 38 scanf("%d",&a[i]); 39 if(a[i]!=pre) 40 { 41 k++; 42 aa[k].sta=i; 43 aa[k].end=i;//记录k的始末 44 pre=a[i]; 45 } 46 else aa[k].end=i; 47 pos[i]=k;//记录下标所对应的k 48 } 49 for(int i=1;i<=k;i++) 50 aa[i].num=aa[i].end-aa[i].sta+1; 51 for(int i=1;i<=k;i++) 52 f[i][0]=aa[i].num; 53 for(int j=1;j<=lo[n]+1;j++) 54 for(int i=1;i<=k;i++) 55 if(i+(1<<j)-1<=k) 56 f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//分成等量两段长度为1<<j-1 57 for(int i=1;i<=m;i++) 58 { 59 scanf("%d%d",&x,&y); 60 if(pos[x]==pos[y])cout<<y-x+1<<endl; 61 else 62 { 63 int a1=aa[pos[x]].end; 64 int b1=aa[pos[y]].sta; 65 int n1=a1-x+1; 66 int n2=0; 67 int n3=y-b1+1; 68 int k1=pos[x],k2=pos[y]; 69 int p=lo[k2-k1+1-2];//都是连续区间个数 70 if(k2-k1-1==0)cout<<max(n1,n3)<<endl; 71 else 72 { 73 n2=max(f[k1+1][p],f[k2-1-(1<<p)+1][p]); 74 cout<<max(max(n1,n2),n3)<<endl; 75 } 76 } 77 } 78 } 79 return 0; 80 }
总结:
1.RMQ求最值的用法
2,RMQ(线段树)的应用,不完全用,先分成三部分,中间一部分用RMQ
3,RMQ:f[i][j]初始化f[i][0]=a[i];
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]),递推,for(j:1-log2(n))for(i:1-n)[j是外层循环,i是内层,先推两个的最大值,然后再是四个,八个]
4.看清题目,是多组数据