HDU 1806 Frequent values(RMQ)

Frequent values

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 778    Accepted Submission(s): 259


Problem 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
Hint
A naive algorithm may not run in time!
 

 

Source
 

 

Recommend
linle
 
 
此题用线段树做也是挺方便的。
用了ST的RMQ做,速度挺快的。
 
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAXN=100010;

int a[MAXN];
int b[MAXN];
int dp[MAXN][20];

void makeRMQ(int n,int b[])
{
    for(int i=0;i<n;i++)
      dp[i][0]=b[i];
    for(int j=1;(1<<j)<=n;j++)
      for(int i=0;i+(1<<j)-1<n;i++)
        dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int s,int v)
{
    int k=(int)(log(v-s+1.0)/log(2.0));
    return max(dp[s][k],dp[v-(1<<k)+1][k]);
}

int bi_search(int s,int t)
{
    int tmp=a[t];
    int l=s;
    int r=t;
    int mid;
    while(l<r)
    {
        mid=((l+r)>>1);
        if(a[mid]>=tmp)r=mid;
        else l=mid+1;
    }
    return r;
}

int main()
{
  //  freopen("in.txt","r",stdin);
  //  freopen("out.txt","w",stdout);
    int n,q;
    int s,t;
    while(scanf("%d",&n),n)
    {
        scanf("%d",&q);
        for(int i=0;i<n;i++)
          scanf("%d",&a[i]);
        int tmp;
        for(int i=n-1;i>=0;i--)
        {
            if(i==n-1)tmp=1;
            else
            {
                if(a[i]==a[i+1])tmp++;
                else tmp=1;
            }
            b[i]=tmp;
        }
        makeRMQ(n,b);
        while(q--)
        {
            scanf("%d%d",&s,&t);
            s--;
            t--;
            /*int ans=1;
            t--;
            while(s<=t)
            {
                if(a[t]!=a[t+1])break;
                ans++;
                t--;
            }*/
            int temp=bi_search(s,t);//找到区间中值和右端点相同的位置
            int ans=t-temp+1;
            t=temp-1;
            if(s>t)printf("%d\n",ans);
            else printf("%d\n",max(ans,rmq(s,t)));
        }
    }
    return 0;
}

 

posted on 2012-09-20 22:18  kuangbin  阅读(1716)  评论(0编辑  收藏  举报

导航

JAVASCRIPT: