• 【暑假】[实用数据结构]UVa11235 Frequent values


    UVa 11235 Frequent values

    Time Limit: 2000MS   Memory Limit: 65536K

    Total Submissions: 11241

      Accepted: 4110

     

    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

    -----------------------------------------------------------------------------------------------------------------------------------------------------------

    题目:

      对于询问(L,R)输出该范围内的最多的重复次数。

    思路:

      一开始想到的是将每个数的出现次数加入RMQ.A 这样就可以满足题意。

      但考虑到一个数可以重复出现多次时间方面不是很乐观,还有更优的方法: 将每段相同数作为一结点,该数字出现次数作为结点信息加入RMQ.A。问题就是如何将pos(L,R)转化到段上(pos是位置),为每一个pos添加信息:

    1. num[u]: 表示数字u属于的结点标号
    2. left[u]和right[u]:分别表示该数字段左端点与右端点。

      那么对于询问(L,R)可以如是组织答案:

           ans=max{ right[L]-L+1 , R-left[R]+1 , RMQ(num[L]+1,num[R]-1)}

      

      需要注意的是一些边界的处理,如果处理不好可能会死程序。

     

      *在长度与序号的运算中:

         序号+长度-1=序号

         序号-长度+1=序号   

         序号-序号+1=长度

    代码:

     1 #include<cstdio>
     2 #include<vector>
     3 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
     4 using namespace std;
     5 
     6 const int maxn = 100000+10;
     7 const int maxlog = 20;
     8 
     9 struct RMQ{ //范围最大值 
    10 int d[maxn][maxlog]; 
    11   
    12   //DP 
    13   void init(const vector<int>& A){
    14       int n=A.size();
    15       FOR(i,0,n) d[i][0]=A[i];
    16       for(int j=1;(1<<j)<=n;j++)
    17        for(int i=0;i+(1<<j)-1<n;i++)  //i+(1<<j)-1  :序号 < n 
    18         d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]); //1<<(j-1)
    19   }
    20   
    21   int Query(int L,int R){ //建立在L<R的基础上 
    22       int k=0;
    23       while(1<<(k+1) <= (R-L+1)) k++;
    24       return max(d[L][k],d[R-(1<<k)+1][k]); 
    25   } 
    26 };
    27 
    28 int a[maxn],num[maxn],left[maxn],right[maxn];
    29 int n,m;
    30 RMQ rmq;
    31 
    32 int main(){
    33   while(scanf("%d%d",&n,&m)==2 && n){
    34       FOR(i,0,n) scanf("%d",&a[i]);
    35       a[n]=a[n-1]+1;  //哨兵 //保证最后一段的处理 **
    36     vector<int> count;                      
    37     //RMQ.A中每一段相同数字为一结点,数值为长度,所以RMQ 提供操作Query为 L段到R段的最大长度 
    38     int start=-1;
    39     FOR(i,0,n+1) if(i==0 || a[i-1]<a[i]){  //新的一段 
    40     //处理旧的一段 
    41         if(i>0){   //if i==0 则只有start重载为0 
    42             count.push_back(i-start);    //将旧一段的长度加入RMQ.A 
    43             FOR(j,start,i){             //赋值 旧一段每个位置p 信息num left right 
    44                 num[j]=count.size()-1; left[j]=start; right[j]=i-1;
    45                 //num记录结点标号  
    46             }
    47         }
    48         start = i;  //开始新的一段 start记录开始一段的头序号 
    49     }
    50     rmq.init(count);
    51     FOR(i,0,m){
    52         int L,R;
    53         scanf("%d%d",&L,&R); L--;R--;  //缩 序号 
    54         int ans=0;
    55         if(num[L]==num[R]) ans=R-L+1;  //特殊情况 LR处于一段 
    56         else {
    57             ans=max(right[L]-L+1,R-left[R]+1);
    58             if(num[L]+1 < num[R]) ans=max(ans,rmq.Query(num[L]+1,num[R]-1));
    59             //if num[L]+1==num[R]则RMQ 调用出错 
    60         }
    61         printf("%d
    ",ans);
    62     }
    63   }
    64   return 0;    
    65 }

     

  • 相关阅读:
    linux 安装mysql及配置
    django restframework的应用
    python uuid的连接及简单应用
    Flink开发-Flink的计算模型和接口
    数据仓库-基本框架和内容
    数据仓库-需求沟通和开发示例
    Spark开发-开发总览
    Hive 高阶应用开发示例(二)
    Hive 高阶应用开发示例(一)
    Spark开发-关联分析
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4711527.html
Copyright © 2020-2023  润新知