查询某个区间出现最多的数字.
我都不知道是怎么A的 ==!!
有个重要的特征就是输入的数组中 A[I]<=A[I+1],所以我们可以先离散化,然后记录下每个数字出现的开始位置,和结束位置.
然后就是线段树,每个点除了存左右区间,还要存左边的最多,以及右边的最多,以及最左最右的数字,和这个区间的最多,和最多的这个数字.
然后就是区间的合并了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
inline int input()
{
int ret=0;bool IsN=0;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') IsN=1;c=getchar();}
while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
return IsN?-ret:ret;
}
using namespace std;
map<int,int>m;
map<int,int>::iterator it;
int n,q,k;
int a[100000+10];
int s[100000+10],e[100000+10];
struct node
{
int l,r;
int len,ll,lr;
int lnum,rnum,num;
}root[100010*4];
inline void pushUp(int t)
{
int l=root[t*2].r-root[t*2].l+1;
int r=root[t*2+1].r-root[t*2+1].l+1;
root[t].lnum=root[t*2].lnum;
root[t].rnum=root[t*2+1].rnum;
root[t].ll=root[t*2].ll;
if(root[t*2].ll==l&&root[t*2].rnum==root[t*2+1].lnum) root[t].ll+=root[t*2+1].ll;
root[t].lr=root[t*2+1].lr;
if(root[t*2+1].lr==r&&root[t*2].rnum==root[t*2+1].lnum) root[t].lr+=root[t*2].lr;
int a1=root[t*2].len,a2=root[t*2+1].len;
int a3=0;
if(root[t*2].rnum==root[t*2+1].lnum)
{
int x=m[root[t*2].rnum];
int tt=min(e[x],root[t*2+1].r);
int ss=max(s[x],root[t*2].l);
a3=tt-ss+1;
}
int a=0,id=0;
if(a1>a) a=a1,id=root[t*2].num;
if(a2>a) a=a2,id=root[t*2+1].num;
if(a3>a) a=a3,id=root[t*2].rnum;
root[t].num=id,root[t].len=a;
}
inline void build(int t,int x,int y)
{
root[t].l=x,root[t].r=y;
if(x==y)
{
root[t].num=root[t].lnum=root[t].rnum=a[x];
root[t].len=root[t].ll=root[t].lr=1;
return;
}
int mid=(x+y)>>1;
build(t*2,x,mid);
build(t*2+1,mid+1,y);
pushUp(t);
}
inline int query(int t,int x,int y)
{
int l=root[t].l,r=root[t].r;
if(l==x&&r==y)
{
return root[t].len;
}
int mid=(l+r)>>1;
if(y<=mid) return query(t*2,x,y);
else if(x>mid) return query(t*2+1,x,y);
else
{
int a1=query(t*2,x,mid);
int a2=query(t*2+1,mid+1,y);
int a3=0;
if(root[t*2].rnum==root[t*2+1].lnum)
{
int xx=m[root[t*2].rnum];
int tt=min(root[t*2].lr,root[t*2].r-x+1);
int ss=min(root[t*2+1].ll,y-root[t*2+1].l+1);
a3=tt+ss;
}
return max(a1,max(a2,a3));
}
}
int main()
{
while(1)
{
n=input();
if(n==0) break;
q=input();
for(int i=1;i<=n;i++) a[i]=input(),m[a[i]]=1;
k=1;
for(it=m.begin();it!=m.end();it++) it->second=k++;
int now=a[1],p=1,i=1;
for(;i<=n;)
{
s[m[now]]=i;
while(i<=n&&a[i]==now) i++;
e[m[now]]=i-1;
if(i<=n) now=a[i];
}
build(1,1,n);
for(int i=0;i<q;i++)
{
int x,y;
x=input(),y=input();
printf("%d\n",query(1,x,y));
}
}
}
再贴个LRJ书上的做法
#define N 100005
int n,q,a[N],val[N],cnt[N],l[N],r[N],id[N];
int x,y,xx,yy,b,num,s,pos;
struct node{
int l,r,val;
}root[N<<2];
inline void build(int t,int x,int y){
root[t].l=x,root[t].r=y;
if(x==y){
root[t].val=cnt[x];return;
}
else{
int mid=(x+y)>>1;
build(L,x,mid),build(R,mid+1,y);
root[t].val=max(root[L].val,root[R].val);
}
}
inline int query(int t,int x,int y){
int l=root[t].l,r=root[t].r;
if(l==x && r==y) return root[t].val;
int mid=(l+r)>>1;
if(y<=mid) return query(L,x,y);
else if(x>mid) return query(R,x,y);
return max(query(L,x,mid),query(R,mid+1,y));
}
int main(){
while(1){
n=input();if(n==0) break;
q=input();
clr(val),clr(cnt),clr(l),clr(r),clr(id);
rep(i,1,n+1) a[i]=input();
a[n+1]=INF;
b=a[1],s=1,num=1,pos=0;
rep(i,2,n+2){
if(a[i]==b) num++;
else{
val[pos]=b,l[pos]=s,r[pos]=i-1,cnt[pos++]=num,s=i,b=a[i],num=1;
}
}
rep(i,0,pos){
rep(j,l[i],r[i]+1){
id[j]=i;
}
}
/*
rep(i,0,pos){
printf("%d %d %d %d \n",val[i],cnt[i],l[i],r[i]);
}*/
build(1,0,pos-1);
rep(ca,1,q+1){
x=input(),y=input();
xx=id[x],yy=id[y];
int Max=max(min(r[xx],y)-x+1,y-max(x,l[yy])+1);
xx++,yy--;
if(xx<=yy){
Max=max(Max,query(1,xx,yy));
}
output(Max);
}
}
return 0;
}