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
题目给出一个不下降序列,查询时让求出区间内的出现次数最多的数出现的次数
题目问题在于怎么记录区间内数出现的次数,题目难点是将一个区间划分为左右子区间时怎么求,方法是用线段树来记录num是当前区间出现频率最多的数,lnum记录区间最左边的数在本区间内出现的次数,r记录区间最y右边的数在本区间内出现的次数,那么刚好在于数列中数是连续的,所以对左右子区间是否连续(左区间最右的数与右区间最左的数是否相同)进行判断处理
代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
#define M 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n,q;
struct node{
int l,r,num,lnum,rnum; //num是当前区间出现频率最多的数,lnum记录区间最左边的数在本区间内出现的次数,r记录区间最y右边的数在本区间内出现的次数
}tree[M<<2];
int p[M];
inline void pushup(int rt)
{
int l=tree[rt].l;
int r=tree[rt].r;
int m=(l+r)>>1;
int temp;
bool flag=false;
if(p[tree[rt<<1].r]==p[tree[rt<<1|1].l]) //两个子区间能连续
flag=true;
if(flag)
temp=tree[rt<<1].rnum+tree[rt<<1|1].lnum; //两区间公共数的出现次数
else
temp=0;
tree[rt].num=max(max(tree[rt<<1].num,tree[rt<<1|1].num),temp);
tree[rt].lnum=tree[rt<<1].lnum; //区间lnum与左子区间的lnum相同
if(flag&&tree[rt<<1].lnum==(m-l+1)) //子区间连续且左子区间中全为同一个数
tree[rt].lnum+=tree[rt<<1|1].lnum;
tree[rt].rnum=tree[rt<<1|1].rnum;
if(flag&&tree[rt<<1|1].rnum==(r-m))
tree[rt].rnum+=tree[rt<<1].rnum;
}
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
if(l==r)
{
tree[rt].num=tree[rt].lnum=tree[rt].rnum=1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int query(int L,int R,int rt)
{
if(L<=tree[rt].l&&tree[rt].r<=R)
{
return tree[rt].num;
}
int m=(tree[rt].l+tree[rt].r)>>1;
int ret=-500000;
if(R<=m) ret=max(ret,query(L,R,rt<<1));
else if(L>m) ret=max(ret,query(L,R,rt<<1|1));
else
{
ret=max(ret,query(L,m,rt<<1));
ret=max(ret,query(m+1,R,rt<<1|1));
if(p[tree[rt<<1].r]==p[tree[rt<<1|1].l])
{
int temp=min(tree[rt<<1].rnum,m-L+1)+min(tree[rt<<1|1].lnum,R-m);//子区间连续,要要查询区间范围是[L,R]
ret=max(temp,ret);
}
}
return ret;
}
int main()
{
int a,b,i;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
scanf("%d",&q);
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
}
build(1,n,1);
while(q--)
{
scanf("%d%d",&a,&b);
printf("%d\n",query(a,b,1));
}
}
return 0;
}