Frequent values
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 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 |
[Submit] [Go Back] [Status] [Discuss]
这个题绝对是原创!!!
哎~提起这个题真的好苦逼,是比赛的一个题,比赛时真的感觉是对的,但是时间不够,还是没有做出来,结束后
做了好久还是无果,看题解感觉和别人的一样的思路啊,最后决定独立自主,自力更生,终于做出来了,%>_<%,
bug了好久,在这里,我就留下我bug的痕迹吧,方便日后看
题意:n个数,m次询问,每一次 a b,输出出现最多次数的数的次数,不过题目说序列为不递减序列,所以相同的数为邻居
思路:线段树,因为时间很紧,具体程序运行过程我注释在程序中
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)
using namespace std;
#define N 100005
struct stud{
int le,ri; //区间左,右端点
int lle,rri; //区间左值,右值
int ls,rs,ms;//区间跟左值(右值)相同的数的个数
}f[N*4]; //如果不懂,后面有提试
int a[N];
void pushup(int pos)
{
f[pos].lle=f[L(pos)].lle;
f[pos].rri=f[R(pos)].rri;
f[pos].ls=f[L(pos)].ls;
f[pos].rs=f[R(pos)].rs;
f[pos].ms=max(f[L(pos)].ms,f[R(pos)].ms);
if(f[L(pos)].rri==f[R(pos)].lle)
{
if(f[L(pos)].ls==f[L(pos)].ri-f[L(pos)].le+1)
f[pos].ls+=f[R(pos)].ls;
if(f[R(pos)].rs==f[R(pos)].ri-f[R(pos)].le+1)
f[pos].rs+=f[L(pos)].rs;
int temp=f[L(pos)].rs+f[R(pos)].ls;
f[pos].ms=max(f[pos].ms,temp);
}
}
void build(int pos,int le,int ri)
{
f[pos].le=le;
f[pos].ri=ri;
if(le==ri)
{
f[pos].lle=f[pos].rri=a[le];
f[pos].ls=f[pos].rs=f[pos].ms=1;
return ;
}
int mid=MID(le,ri);
build(L(pos),le,mid);
build(R(pos),mid+1,ri);
pushup(pos); //想想什么是递归,
//当前面的build执行完了再执行这一步(记住上一步build中也有 pushup)
//自己模拟过程
}
int query(int pos,int le,int ri)
{
if(f[pos].le>=le&&f[pos].ri<=ri)
{
// printf("le=%d ri=%d temp=%d\n",le,ri,f[pos].ms);
return f[pos].ms;
}
int mid=MID(f[pos].le,f[pos].ri);
if(mid>=ri)
return query(L(pos),le,ri);
else
if(mid<le)
return query(R(pos),le,ri);
else
{
int temp=max(query(L(pos),le,mid),query(R(pos),mid+1,ri));
//printf("temp=%d\n",temp);
if(f[L(pos)].rri==f[R(pos)].lle)
{
// printf("L(pos).le=%d L(pos).ri=%d R(pos).le=%d R(pos).ri=%d ",f[L(pos)].le,f[L(pos)].ri,f[R(pos)].le,f[R(pos)].ri);
//printf("rri=%d lle=%d\n",f[L(pos)].rri,f[R(pos)].lle);
//printf("f[L(pos)].rs=%d f[R(pos)].ls=%d\n",f[L(pos)].rs,f[R(pos)].ls);
temp=max(temp,min(f[L(pos)].rs,mid-le+1)+min(f[R(pos)].ls,ri-mid));
//上面我原来错的地方!!!!!
//原错误代码 temp=max(temp,min(f[L(pos)].rs,mid-f[L(pos).le+1)+min(f[R(pos)].ls,f[R(pos).ri-mid));
//想知道我怎么知道自己错的地方,就去掉前面的注释,就用下面简单的测试样例
}
//printf("le=%d ri=%d temp=%d\n",le,ri,temp);
return temp;
}
}
int main()
{
int n,m,le,ri,t,i;
while(scanf("%d",&n),n)
{
scanf("%d",&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
// for(i=1;i<40;i++)
//if(f[i].le!=0)
// printf("%d: le=%d ri=%d lle=%d rri=%d ls=%d rs=%d ms=%d\n",i,f[i].le,f[i].ri,f[i].lle,f[i].rri,f[i].ls,f[i].rs,f[i].ms);
//去掉上面几行备注,这里可以帮你理解build过程
while(m--)
{
scanf("%d%d",&le,&ri);
printf("%d\n",query(1,le,ri));
}
}
return 0;
}
/*
10 8
-1 -1 1 1 1 1 3 10 10 10
5 10
*/