Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 13317 | Accepted: 4894 |
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
Source
详细参考刘汝佳的算法训练指南第198页,看了就懂了。
AC代码:
#include<stdio.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int a[100010];
int val[100010],counter[100010];
int num[100010],Left[100010],Right[100010];
int d[100100][110];
int n,q;
void RMQ_init(){
int i,j,k;
int tmp;
val[1]=a[1];
k=num[1]=Left[1]=1;
for(i=2;i<=n;i++){
if(a[i]!=val[k]){
Right[k]=i-1;
counter[k]=Right[k]-Left[k]+1;
k++;
Left[k]=i;
val[k]=a[i];
}
num[i]=k;
}
Right[k]=n;
counter[k]=Right[k]-Left[k]+1;
for(i=1;i<=k;i++)
d[i][0]=counter[i];
for(j=1;(1<<j)<=k;j++)
for(i=1;i+(1<<j)-1<=k;i++){
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
}
int RMQ(int x,int y){
int k=0;
while((1<<(k+1))<=y-x+1) k++;
return max(d[x][k],d[y-(1<<k)+1][k]);
}
int main(){
while(scanf("%d",&n)!=EOF){
if(n==0)
break;
scanf("%d",&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
RMQ_init();
while(q--){
int x,y;
scanf("%d%d",&x,&y);
if(num[x]==num[y]){
printf("%d\n",y-x+1);
}
else{
int ans;
ans=max(Right[num[x]]-x+1,y-Left[num[y]]+1);
if(num[x]+1<=num[y]-1){
ans=max(ans,RMQ(num[x]+1,num[y]-1));
}
printf("%d\n",ans);
}
}
}
return 0;
}