zoukankan      html  css  js  c++  java
  • UVa 11235 Frequent values

    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
    

    A naive algorithm may not run in time!

    整个数组是非降序的,所以所有相同的元素都是相邻的。可以把整个数组进行游程编码(Run Length Encoding,RLE)。比如样例中的-1 -1 1 1 1 1 3 10 10 10可以编码为(-1,2),(1,4),(3,1),(10,3),其中(a,b)表示有b个连续的a,在程序中,我用了value数组和number数组分别表示第i段的数值(a)和出现的次数(b)。

    数组pos[i],Left[i],Right[i]分别保存位置i的元素所在段的下标,第一次出现这个数值的下标和最后一次出现这个数值的下标。

    则每次询问的结果就是下面三个数的最大值:

      1、从L到L所在段结束处的元素个数(Right[L]-L+1)

      2、从R到R所在段开始处的元素个数(R-Left[R]+1)

      3、中间部分(Right[L]+1到Left[R]-1)出现次数最多的元素的出现次数,即从pos[L]+1到pos[R]-1段中number的最大值

    其中第三条是一个RMQ问题,可以用Tarjan的Sparse-Table算法求解(Sparse-Table算法讲解: http://www.cnblogs.com/lzj-0218/p/3539367.html)。

    另外此题数据范围似乎有问题,刚开始数组大小开100050时总是RE,一怒之下全改成了200050就AC了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 int n,t;
     9 int a[200050],value[200050],number[200050],Left[200050],Right[200050],pos[200050];
    10 int rmq[200050][100];
    11 
    12 void RMQ_init()
    13 {
    14     for(int i=1;i<=n;i++)
    15         rmq[i][0]=number[i];
    16     for(int j=1;(1<<j)<=n;j++)
    17         for(int i=1;i+j-1<=n;i++)
    18             rmq[i][j]=max(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);
    19 }
    20 
    21 int RMQ(int l,int r)
    22 {
    23     int k=0;
    24     while( (1<<(k+1)) <= r-l+1 )
    25         k++;
    26     return max(rmq[l][k],rmq[r-(1<<k)+1][k]);
    27 }
    28 
    29 int Max(int a,int b,int c)
    30 {
    31     return a>b?(a>c?a:c):(b>c?b:c);
    32 }
    33 
    34 int main()
    35 {
    36     while(scanf("%d",&n)==1&&n)
    37     {
    38         int q;
    39 
    40         t=1;
    41         memset(number,0,sizeof(number));
    42 
    43         scanf("%d",&q);
    44         for(int i=1;i<=n;i++)
    45         {
    46             scanf("%d",&a[i]);
    47             if(i==1)
    48             {
    49                 Left[0]=1;
    50                 value[1]=a[0]=a[1];
    51             }
    52             if(a[i]!=a[i-1])
    53             {
    54                 Left[i]=i;
    55                 value[++t]=a[i];
    56                 for(int j=i-1;j>=0&&a[j]==a[i-1];j--)
    57                     Right[j]=i-1;
    58             }
    59             else
    60                 Left[i]=Left[i-1];
    61             pos[i]=t;
    62             number[t]++;
    63         }
    64         for(int i=n;i>=0&&a[i]==a[n];i--)
    65             Right[i]=n;
    66 
    67         RMQ_init();
    68 
    69         int l,r;
    70         for(int i=1;i<=q;i++)
    71         {
    72             scanf("%d %d",&l,&r);
    73             printf("%d
    ",a[l]==a[r]?r-l+1:Max(Right[l]-l+1,r-Left[r]+1,pos[l]+1<=pos[r]-1?RMQ(pos[l]+1,pos[r]-1):-1) );
    74         }
    75 
    76     }
    77 
    78     return 0;
    79 }
    [C++]
  • 相关阅读:
    HTML连载10-details标签&summary标签&marquee标签
    [刷题] 7-14 然后是几点
    [刷题] 7-18 出租车计价 (15 分)
    [刷题] PTA 7-20 简单计算器
    [刷题] PTA 7-22 用天平找小球
    [刷题] PTA 7-24 猜数字游戏
    [刷题] PTA 7-28 求整数的位数及各位数字之和
    [刷题] PTA 7-30 念数字
    [刷题] PTA 7-37 输出整数各位数字
    [刷题] PTA 7-35 猴子吃桃问题
  • 原文地址:https://www.cnblogs.com/lzj-0218/p/3539354.html
Copyright © 2011-2022 走看看