Frequent values
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 58 Accepted Submission(s) : 22
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
<p>The input consists of several test cases. Each test case starts with a line containing two integers <strong>n</strong> and <strong>q</strong> (<i>1 ≤ n, q ≤ 100000</i>). The next line contains <strong>n</strong> integers <strong>a<sub>1</sub>
, ... , a<sub>n</sub></strong> (<i>-100000 ≤ a<sub>i</sub> ≤ 100000</i>, for each <i>i ∈ {1, ..., n}</i>) separated by spaces. You can assume that for each <i>i ∈ {1, ..., n-1}: a<sub>i</sub> ≤ a<sub>i+1</sub></i>. The following <strong>q</strong> lines contain
one query each, consisting of two integers <strong>i</strong> and <strong>j</strong> (<i>1 ≤ i ≤ j ≤ n</i>), which indicate the boundary indices for the< br>query.</p><p>The last test case is followed by a line containing a single <i>0</i>.</p>
Output
<p>For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.</p>
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
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cstring>
#include<cmath>
#define M 100001
using namespace std;
struct node
{
int l,r;
int lmax,rmax,amax;//记lmax为最左边的个数,同理
}tree[M*4];
int a[M];
void build(int id,int l,int r)
{
tree[id].l=l;
tree[id].r=r;
if(l==r)
{
tree[id].lmax=tree[id].rmax=tree[id].amax=1;
return;
}
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
int count;
if(a[tree[id*2].r]==a[tree[id*2+1].l])
count=tree[id*2].rmax+tree[id*2+1].lmax;
else
count=0;
tree[id].amax=max(max(tree[id*2].amax,tree[id*2+1].amax),count);
//此时还没有更新lmax最左边数字的连续的个数,还有最右边的数字的连续的个数,所以接下来要判断
tree[id].lmax=tree[id*2].lmax;//但是此时有bug,假如左子树左右的数相同,并且与右子树左边的相等,则tree[id]就不准确了
if(tree[id*2].lmax==mid-l+1&&a[tree[id*2].r]==a[tree[id*2+1].l])
tree[id].lmax=mid-l+1+tree[id*2+1].lmax;
tree[id].rmax=tree[id*2+1].rmax;
if(tree[id*2+1].rmax==r-mid&&a[tree[id*2+1].l]==a[tree[id*2].r])//之前一直有疑问,后来想到当范围内的数全相等时,他的左右max相等
tree[id].rmax=r-mid+tree[id*2].rmax;
//build(id*2,l,mid);
//build(id*2+1,mid+1,r);
}
int query(int id,int l,int r)
{
if(tree[id].l==l&&tree[id].r==r)
return tree[id].amax;
int mid=(tree[id].l+tree[id].r)/2;
if(r<=mid)
return query(id*2,l,r);
else if(l>mid)
return query(id*2+1,l,r);
else
{
int a1=query(id*2,l,mid);
int a2=query(id*2+1,mid+1,r);
int a3=0;
if(a[tree[id*2].r]==a[tree[id*2+1].l])
{
a3=min(tree[id*2].rmax,mid-l+1)+min(tree[id*2+1].lmax,r-mid);
}
return max(max(a1,a2),a3);
}
}
int main()
{
int n;
int p;
int x,y;
while(scanf("%d",&n)!=0)
{
if(n==0)
break;
scanf("%d",&p);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,1,n);
for(int i=0;i<p;i++)
{
scanf("%d%d",&x,&y);
cout<<query(1,x,y)<<endl;
}
}
return 0;
}