[POJ] 3368 / [UVA] 11235

2007/2008 ACM International Collegiate Programming Contest 
University of Ulm Local Contest

Problem F: Frequent values

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 Specification

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 Specification

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

题解:因为序列a1,a2,a3...an是不下降的,所以相同的数字肯定连续集中在一段。维护d[i][0]为相同数字从左到右分别从1到n开始编号,例如样例中的d[i][0]从左到右为 1,2,1,2,3,4,1,1,2,3。这样就转化成了RMQ问题。因为没有中途修改a[i]的值,所以可以用Sparse-Table算法,d[i][j]表示从i开始长度为2^i的一段元素的最大值。维护数组Left[i],Right[i]分别为相同数字连续一段最左端的编号和最右端的编号,例如样例中的Left[i]分别为:1,1,3,3,3,3,7,8,8,8。所以,序列分布共有以下几种情况:

              
     [1] ans=max(Right[i]-L+1,R-Left[j]+1)
     [2] ans=R-L+1

     [3] ans=max(max(Right[i]-L+1,R-Left[j]+1),RMQ(k))

代码:
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<ctype.h>
  5 #include<stdlib.h>
  6 #include<stdbool.h>
  7 
  8 #define rep(i,a,b)      for(i=(a);i<=(b);i++)
  9 #define red(i,a,b)      for(i=(a);i>=(b);i--)
 10 #define clr(x,y)        memset(x,y,sizeof(x))
 11 #define sqr(x)          (x*x)
 12 #define LL              long long
 13 
 14 int i,j,n,m,maxn,q,
 15     a[100003],d[100003][50],Left[100003],Right[100003];
 16 
 17 void pre()
 18 {
 19     clr(d,0);
 20     clr(Left,0);
 21     clr(Right,0);
 22     clr(a,0);
 23 }
 24 
 25 int max(int a,int b)
 26 {
 27     if(a>b) return a;
 28     return b;
 29 }
 30 
 31 int RMQ_init()
 32 {
 33     int i,j;
 34      
 35     for(j=1;(1<<j)<=n;j++)
 36         for(i=1;i+(1<<j)-1<=n;i++)
 37         d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
 38     
 39     return 0;
 40         
 41 }
 42 
 43 int RMQ(int L,int R)
 44 {
 45     int k;
 46     k=0;
 47     
 48     while(1<<(k+1)<=R-L+1) k++;
 49  
 50     maxn=max(d[L][k],d[R-(1<<k)+1][k]);;
 51    
 52     return 0;
 53     
 54 }
 55 
 56 int Num_init()
 57 {
 58     int i;
 59 
 60     a[0]=35113;
 61     rep(i,1,n)
 62         if(a[i]!=a[i-1]) Left[i]=i;
 63         else Left[i]=Left[i-1];
 64   
 65     a[n+1]=35113;
 66     red(i,n,1)
 67         if(a[i]!=a[i+1]) Right[i]=i;
 68         else Right[i]=Right[i+1];
 69     
 70     
 71     return 0;
 72 }
 73 
 74 int main()
 75 {
 76     int i,x,y;
 77     
 78      while(true) {
 79          pre();    
 80          scanf("%d",&n); 
 81         
 82          if(n==0) exit(0);
 83          scanf("%d",&q);
 84          a[0]=35113;
 85          rep(i,1,n) {
 86             scanf("%d",&a[i]);
 87             if(a[i]!=a[i-1]) d[i][0]=1;
 88             else d[i][0]=d[i-1][0]+1;
 89             
 90          }
 91            
 92         Num_init();  
 93         RMQ_init();
 94 
 95         while(q--) {
 96             scanf("%d%d",&x,&y);
 97             if(Left[x]==Left[y]) printf("%d
",y-x+1);
 98             else { 
 99                 if(Right[x]+1==Left[y]) printf("%d
",max(Right[x]-x+1,y-Left[y]+1));
100                 else {       
101                      RMQ(Right[x]+1,Left[y]-1);
102                      printf("%d
",max(max(Right[x]-x+1,y-Left[y]+1),maxn));
103                 }
104             }
105         }
106     }   
107     
108     
109     return 0;
110 }


 
原文地址:https://www.cnblogs.com/sxiszero/p/3913715.html