Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 13771 | Accepted: 5045 |
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
#include<stdio.h>
#define MAX_N 500000
struct node{
int l;
int r;
int max;
};
struct msg{
int value;
int start;
int end;
};
node tree[3*MAX_N];
int a[MAX_N+5];
int b[MAX_N+5];
int c[MAX_N+5];
msg inv[MAX_N+5];
int max(int x,int y){
if(x>y)
return x;
else
return y;
}
void swap(int &s,int &e){
s=s^e;
e=s^e;
s=s^e;
}
void build_tree(int left,int right,int root){
tree[root].l=left;
tree[root].r=right;
if(left==right){
tree[root].max=b[left];
return;
}
int mid=(left+right)/2;
build_tree(left,mid,root*2);
build_tree(mid+1,right,root*2+1);
tree[root].max=max(tree[root*2].max,tree[root*2+1].max);
}
int find_max(int left,int right,int root){
if(left==tree[root].l&&right==tree[root].r)
return tree[root].max;
int mid=(tree[root].l+tree[root].r)/2;
if(right<=mid)
return find_max(left,right,root*2);
else if(left>mid)
return find_max(left,right,root*2+1);
else
return max(find_max(left,mid,root*2),find_max(mid+1,right,root*2+1));
}
int main(){
int n,m,i,len,inv_len,s,e;
while(scanf("%d",&n)!=EOF){
if(n==0)
break;
scanf("%d",&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
len=0,inv_len=0;
b[++len]=1;
c[1]=1;
inv[++inv_len].value=a[1];
inv[inv_len].start=1;
for(i=2;i<=n;i++){
if(a[i]==a[i-1]){
b[len]++;
c[i]=c[i-1];
}
else{
b[++len]=1;
inv[inv_len].end=i-1;
inv[++inv_len].value=a[i];
inv[inv_len].start=i;
c[i]=c[i-1]+1;
}
}
inv[inv_len].end=n;
build_tree(1,len,1);
for(i=1;i<=m;i++){
scanf("%d%d",&s,&e);
if(s>e)
swap(s,e);
int q1=c[s];
int q2=c[e];
int ans;
if(q2-q1==1){
int max1=inv[q1].end-s+1;
int max2=e-inv[q2].start+1;
ans=max(max1,max2);
}
else if(q2-q1==0){
ans=e-s+1;
}
else{
int max1=inv[q1].end-s+1;
int max2=e-inv[q2].start+1;
int max3=find_max(c[inv[q1].end+1],c[inv[q2].start-1],1);
ans=max(max(max1,max2),max3);
}
printf("%d\n",ans);
}
}
return 0;
}