• [RMQ][ST算法]Frequent values


    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

    思路:预处理第i的数在1~i中出现了多少次,得到freq[i],这样就转化为了对freq数组的RMQ了,即求max{freq[x~y]};但其实不是这样的,freq[x]中记录的频率可能要大于a[x]实际在区间[x,y]出现的次数,同理freq[y]也未必准确;
    那我们就把区间[x,y]分成两段,一段是[x,t],一段是[t+1,y];t是与a[x]相等的最后一个元素的下标,那么答案即为max(t-x+1,max{freq[t+1~y]});
    AC代码:
    #include <iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    
    int n,q;
    int a[100010];
    int fre[100010];
    int bl[100010];//a[x]所属区域,也可以不要该数组,则r[i]的含义就是a[i]出现的最后位置
    int r[100010];//r[i]的含义是区域i的最右下标
    int maxn[100010][20];
    
    void ST(){
       for(int i=1;i<=n;i++) maxn[i][0]=fre[i];
       int k=int(log(n*1.0)/log(2.0));
       for(int j=1;j<=k;j++){
         for(int i=1;i<=n;i++){
            if(i+(1<<j)-1>n) break;
            maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
         }
       }
    }
    
    int query(int x,int y){
      int k=int(log(y-x+1.0)/log(2.0));
      return max(maxn[x][k],maxn[y-(1<<k)+1][k]);
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF&&n){
          scanf("%d",&q);
          int cnt=0;
          scanf("%d",&a[1]),fre[1]=1,bl[1]=++cnt;
          for(int i=2;i<=n;i++) {
            scanf("%d",&a[i]);
            if(a[i]==a[i-1]) fre[i]=fre[i-1]+1,bl[i]=bl[i-1],r[bl[i]]=i;
            else fre[i]=1,bl[i]=++cnt,r[bl[i]]=i;
          }
          ST();
          while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            if(bl[x]==bl[y]) printf("%d
    ",y-x+1);
            else printf("%d
    ",max(r[bl[x]]-x+1,query(r[bl[x]]+1,y)));
          }
        }
        return 0;
    }
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    CodeForces 7B
    CodeForces 4D
    离散化
    线段树入门
    洛谷 P3951 小凯的疑惑(赛瓦维斯特定理)
    Codeforces 1295D Same GCDs (欧拉函数)
    Codeforces 1295C Obtain The String (二分)
    Codeforces 1295B Infinite Prefixes
    Codeforces 1295A Display The Number(思维)
    Codeforces 1294F Three Paths on a Tree(树的直径,思维)
  • 原文地址:https://www.cnblogs.com/lllxq/p/9106471.html
Copyright © 2020-2023  润新知