HDU1806 Frequent values

Problem Description
You are given a sequence of n integers a 1 , a 2 , ... , a n 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 a i , ... , a j . 

 

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 a 1 , ... , a n(-100000 ≤ a i ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: a i ≤ a i+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
现将其离散化,那么就转化成连续区间最值,可用RMQ解决。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 100000+10;
    vector<int> val,cnt;
    int res[maxn][20];
    int num[maxn],lft[maxn],rgt[maxn];
    int n,q;
    void init_RMQ(){
        int nt = cnt.size();
        for(int i = 0; i < nt; i++) res[i][0] = cnt[i];
        for(int j = 1; (1<<j) <= nt; j++){
            for(int i = 0; i+(1<<j)-1 < nt; i++)
                res[i][j] = max(res[i][j-1],res[i+(1<<(j-1))][j-1]);
        }
    }
    int RMQ(int L,int R){
        int k = 0;
        while((1<<(k+1)) <= R-L+1) k++;
        return max(res[L][k],res[R-(1<<k)+1][k]);
    }
    int main(){

        int t,now;
        while(cin >> n &&n){
            cin >> q;
            val.clear();
            cnt.clear();
            scanf("%d",&now);
            cnt.push_back(1);
            for(int i = 1; i < n; i++){
                int t;
                scanf("%d",&t);
                if(t==now)
                    cnt[cnt.size()-1]++;
                else{
                    now = t;
                    cnt.push_back(1);
                }
            }
            init_RMQ();
            int cur = 0;
            for(int i = 0; i < cnt.size(); i++){
                int tl = cur,tr = cur+cnt[i]-1;
                for(int j = 0; j < cnt[i]; j++){
                    num[cur] = i;
                    lft[cur] = tl;
                    rgt[cur++] = tr;
                }
            }

            while(q--){
                int L,R;
                scanf("%d%d",&L,&R);
                if(L > R) swap(L,R);
                L--;R--;
                int sta = num[L],ed = num[R];
                if(sta==ed){
                    printf("%d\n",R-L+1);
                    continue;
                }
                int ans = max(rgt[L]-L+1,R-lft[R]+1);
                sta++;
                ed--;
                if(sta<=ed)
                    ans = max(ans,RMQ(sta,ed));
                printf("%d\n",ans);
            }
        }
        return 0;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值