• [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 }
    
    
    
     
  • 相关阅读:
    顶级Kagglers的心得和技巧
    大数加法
    TensorFlow 2.0高效开发指南
    Java 8 特性 —— Stream
    Java 8 特性 —— 函数式接口
    Java 8 特性 —— 方法引用
    Java 8 特性 —— 默认方法和静态方法
    Java 8 特性 —— lambda 表达式
    Effective Java 读书笔记
    jQuery动态添加、删除按钮及input输入框
  • 原文地址:https://www.cnblogs.com/sxiszero/p/3913715.html
Copyright © 2020-2023  润新知