Frequent values(HDU - 1806 )
Frequent values
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 .
InputThe 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.
OutputFor 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!
题意:查询区间[l,r]中众数的个数.
因为数列是非递减的,所以可以转化为ST表.
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #define N 100005 using namespace std; int maxn[N][64],a[N],pre[N]; int n,q,i,j; int main() { while(scanf("%d",&n)!=EOF&&n) { scanf("%d",&q); memset(maxn,0,sizeof maxn); for(i=1;i<=n;i++) { scanf("%d",&a[i]); if(i==1) { pre[i]=1; continue; } if(a[i]==a[i-1]) pre[i]=pre[i-1]+1; else pre[i]=1; } for(i=1;i<=n;i++) maxn[i][0]=pre[i]; int t=log2(n); for(j=1;j<=t;j++) { for(i=1;i+(1<<j)-1<=n;i++) { maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]); } } while(q--) { int MAX; int l,r; scanf("%d%d",&l,&r); int m=l; while(m<=r&&a[m]==a[m-1])//区间第一个数字要特判. m++; if(r<m) MAX=0; else { int k=log(r-m+1)/log(2); MAX=max(maxn[m][k],maxn[r-(1<<k)+1][k]); } MAX=max(MAX,m-l); printf("%d\n",MAX); } } }