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.
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; }
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想