题意:找一段区间内出现最多的树的个数
思路:我们只关心每个数的个数。所以把每个数的个数用一个新数组保存起来。查询的时候查询一下区间最大值即可。
RMQ查询可以用线段树树状数组或者ST表。其中ST表的查询是O(1)的复杂度。
代码提供了ST表和线段树的函数。
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
using namespace std;
#define MAXN 500010
#define LEN 200010
#define INF 1e9+7
#define MODE 1000000
#define pi acos(-1)
#define g 9.8
typedef long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n,m,q;
struct node{
int num;
int len;
int first;
int last;
};
node ans[MAXN];
int a[MAXN];
int b[MAXN];
int F[MAXN][20];
void SparseTable()
{
for (int i = 0;i<m;i++)
{
F[i][0]=ans[i].len;
}
int nLog = int(log(double(m))/log(2.0));
for (int j = 1;j <= nLog;j++)
{
for (int i = 0;i < m;i++)
{
if ((i + (1 << j) - 1) < m)
{
if(F[i][j-1]>F[i+(1<<(j-1))][j-1])
{
F[i][j]=F[i][j-1];
}
else
{
F[i][j]=F[i+(1<<(j-1))][j-1];
}
}
}
}
}
int RMQ(int nStart,int nEnd)
{
int nLog = (int)(log(double(nEnd - nStart + 1)/log(2.0)));
return max(F[nStart][nLog],F[nEnd - (1 << nLog) + 1][nLog]);
}
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[MAXN<<2];
void PushUp(int rt){
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r){
sum[rt]=ans[l].len;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return sum[rt];
int m=(l+r)>>1;
int ret=0;
if(L<=m)
ret=max(ret,query(L,R,lson));
if(R>m)
ret=max(ret,query(L,R,rson));
return ret;
}
int main()
{
//freopen("out.txt","w",stdout);
while(scanf("%d)",&n))
{
if(n==0)
break;
scanf("%d",&q);
for(int i=0;i<n;i++)
{
scanf("%d",a+i);
ans[i].len=0;
}
m=0;
ans[0].num=a[0];
ans[0].len=1;
ans[0].first=0;
for(int i=1;i<n;i++)
{
if(a[i]==a[i-1])
{
ans[m].len++;
b[i]=m;
}
else
{
ans[m].last=i-1;
m++;
b[i]=m;
ans[m].num=a[i];
ans[m].len=1;
ans[m].first=i;
}
}
ans[m++].last=n-1;
build(0,m-1,1);
while(q--)
{
int r,l;
int R,L;
scanf("%d%d",&l,&r);
l--;
r--;
L=b[l];
R=b[r];
if(R==L)
{
printf("%d\n",r-l+1);
continue;
}
if(ans[L].first<l)
L++;
if(ans[R].last>r)
R--;
if(R<L)
{
int res=-1;
res=max(res,r-ans[R+1].first+1);
res=max(res,ans[L-1].last-l+1);
printf("%d\n",res);
continue;
}
int res=query(L,R,0,m-1,1);
if(ans[L].first-l>res)
{
res=ans[L].first-l;
}
if(r-ans[R].last>res)
{
res=r-ans[R].last;
}
printf("%d\n",res);
}
}
}