[关闭]
@Chilling 2017-02-16T17:53:07.000000Z 字数 2165 阅读 1040

HDU-1806: Frequent values(RMQ)

RMQ


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

题意:输入n,q,然后输入n个数字,q次询问,每次询问一个区间[st,en]中出现最多的数字出现的次数。

分析:由于原数列已经排好序,所以相同的数字一定是在一起的。我们可以O(n)扫描一遍,算出每一个位置上的数字num是从左起第几个num,记为num[i];

如样例,扫描后如下,括号内是num数组值
-1(1) -1(2) 1(1) 1(2) 1(3) 1(4) 3(1) 10(1) 10(2) 10(3)

这样似乎直接求num数组区间[l,r]内的最大值就能得到答案。实际上这样无法得到正确的结果,因为如果查询区间左端点上num值不等于1,就会得到错误的答案。如对样例求[5,7]会得到4。

出现这个错误的原因上面已经说了,因为num数组是对区间[1,n]的计数。

解决方法也很简单,在O(n)倒着扫一遍,对于每个位置上的数字num,求出最右侧的数字为num的位置,记为R[i],如下

-1(2) -1(2) 1(6) 1(6) 1(6) 1(6) 3(7) 10(10) 10(10) 10(10)

这样查询[l,r]时,只要R[l]

当R[l] >= r时,显然[l, r]整个区间都是同一个数字。答案为r-l+1


  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. int a[100005],dp1[100005],dp2[100005],dpmax[100005][17];
  5. int main()
  6. {
  7. int n,q,i,st,en,d,j;
  8. while(scanf("%d",&n),n)
  9. {
  10. scanf("%d",&q);
  11. for(i=1;i<=n;i++)
  12. scanf("%d",&a[i]);
  13. dp1[0]=0,dp1[1]=1;
  14. for(i=2;i<=n;i++)
  15. {
  16. if(a[i]==a[i-1])
  17. dp1[i]=dp1[i-1]+1;
  18. else
  19. dp1[i]=1;
  20. }
  21. dp2[n]=n;
  22. for(i=n-1;i>0;i--)
  23. {
  24. if(a[i]==a[i+1])
  25. dp2[i]=dp2[i+1];
  26. else
  27. dp2[i]=i;
  28. }
  29. /*for(i=1;i<=n;i++)
  30. printf("%d ",dp2[i]);*/
  31. for(i=1;i<=n;i++)
  32. dpmax[i][0]=dp1[i];
  33. for(i=1;(1<<i)<=n;i++)
  34. for(j=1;j+(1<<i)-1<=n;j++)
  35. {
  36. dpmax[j][i]=max(dpmax[j][i-1],dpmax[j+(1<<i-1)][i-1]);
  37. }
  38. while(q--)
  39. {
  40. scanf("%d%d",&st,&en);
  41. if(st>en)
  42. swap(st,en);
  43. if(dp2[st]>=en) //整个区间都是同一个数字
  44. printf("%d\n",en-st+1);
  45. else //查询区间[dp2[st]+1,en]上的最大值,和[st,dp2[st]]区间的值:dp2[st]-st+1进行比较
  46. {
  47. d=0;
  48. while((1<<d+1)<=en-dp2[st])
  49. d++;
  50. printf("%d\n",max(max(dpmax[dp2[st]+1][d],dpmax[en-(1<<d)+1][d]),dp2[st]-st+1));
  51. }
  52. }
  53. }
  54. return 0;
  55. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注