题解:P13984 数列分块入门 9
Defy_HeavenS · · 题解
#6285. 数列分块入门 9 - 题目 - LibreOJ
题面
给出一个长为
技巧
方法 1
分块,块长为
对于
查询时,先用
时间复杂度。预处理
方法 2
分块,块长为
对于
查询时,由于众数一定是整块的众数、散块的所有数中的一个,所以先用
时间复杂度。预处理
关于两者时间复杂度对比
对比
结论:小数据后者优,大数据前者优。本题前者过不了,后者需要卡一点常。
使
代码
const int N=3e5+3,T=2666+3;
int n,m,a[N],L,len,tot,bel[N],be[T],en[T],f[T][T];
vector<int>has,id[N];
void work(int &ans,int &cnt,int Ans,int Cnt){
if(Cnt>cnt||Cnt==cnt&&Ans<ans){
cnt=Cnt,ans=Ans;
}
}
int get(int l,int r,int val){
return upper_bound(id[val].begin(),id[val].end(),r)-lower_bound(id[val].begin(),id[val].end(),l);
}
void init(){
L=sqrt(n*log(n)/log(2))/1.2,len=n/max(1,L),tot=L;
for(int i=1;i<=L;i++){
be[i]=en[i-1]+1,en[i]=i*len;
}
if(en[L]<n){
tot++;
be[tot]=en[tot-1]+1;
en[tot]=n;
}
for(int i=1;i<=tot;i++){
for(int j=be[i];j<=en[i];j++){
bel[j]=i;
}
}
for(int i=1;i<=tot;i++){
int ans=0,cnt=0;
vector<int> c(n+5);
for(int j=be[i];j<=n;j++){
work(ans,cnt,a[j],++c[a[j]]);
f[i][bel[j]]=ans;
}
}
}
int query(int l,int r){
int ans=0,cnt=0;
if(bel[l]==bel[r]){
for(int i=l;i<=r;i++){
work(ans,cnt,a[i],get(l,r,a[i]));
}
return ans;
}
if(bel[l]+1<=bel[r]-1){
work(ans,cnt,f[bel[l]+1][bel[r]-1],get(l,r,f[bel[l]+1][bel[r]-1]));
}
for(int i=l;i<=en[bel[l]];i++){
work(ans,cnt,a[i],get(l,r,a[i]));
}
for(int i=be[bel[r]];i<=r;i++){
work(ans,cnt,a[i],get(l,r,a[i]));
}
return ans;
}
signed main(){
cin>>n;
m=n;
for(int i=1;i<=n;i++){
cin>>a[i];
has.pb(a[i]);
}
sort(all(has)),has.erase(unique(all(has)),has.end());
for(int i=1;i<=n;i++){
a[i]=lower_bound(all(has),a[i])-has.begin()+1;
id[a[i]].pb(i);
}
init();
for(int l,r;m--;){
cin>>l>>r;
cout<<has[query(l,r)-1]<<"\n";
}
return 0;
}