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 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
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;

}

 

你可能感兴趣的:(value)