原题:https://loj.ac/problem/6285
题解:基本题意求[l,r]的最小众数,对于集合 A,B 显然 mode(A and B)属于 mode(A) and B。这样就可以分块,预处理f[i][j]表示i-j的众数。每次查询时暴力查询头尾两块的数和中间块的众数就可以,关于查询x在[l,r]出现了几次,用动态数组存放x的下标,二分查找就好了。可以先给a数组离散化。这道题块的大小大概是
#include<bits/stdc++.h>
#define reg register
#define pa pair<int,int>
using namespace std;
const int N=110000,M=5500;
int n,m,h,a[N],t[N],pos[N],cnt[N],ff[N];
pa f[M][M];//i-j的众数
vector<int> v[N];
inline int rd(){
int x=0;int f=1;char s=getchar();
while(!isdigit(s)) f=(f=='-'?-1:f),s=getchar();
while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
return x*f;
}
inline void clear(int *a,int m){
for(int i=0;i<=m;i++) a[i]=0;return ;
}
inline int ask(int l,int r,int x){
return upper_bound(v[x].begin(),v[x].end(),r)-lower_bound(v[x].begin(),v[x].end(),l);
}
inline int query(int l,int r){
pa mode =make_pair(N,0);
for(reg int i=l,num;i<=min(r,pos[l]*m);i++) {
num=ask(l,r,a[i]);
if(num>mode.second ||(num==mode.second && a[i]<mode.first)) {
mode.first=a[i];mode.second=num;
}
}
if(pos[l]!= pos[r]){
for(reg int i=(pos[r]-1)*m+1,num;i<=r;i++) {
num=ask(l,r,a[i]);
if(num>mode.second ||(num==mode.second && a[i]<mode.first)){
mode.first=a[i];mode.second=num;
}
}
}
if(pos[r]-pos[l]<2) return mode.first;
pa temp=f[pos[l]+1][pos[r]-1];
int num=ask(l,r,temp.first);
if(num>mode.second ||(num==mode.second && temp.first<mode.first)) mode.first=temp.first,mode.second=num;
return mode.first;
}
int main(){
// freopen("input.in","r",stdin);
n=rd();m=pow(n,1.0/3);
for(reg int i=1;i<=n;i++) { a[i]=t[i]=rd(); pos[i]=(i-1)/m+1;}
sort(t+1,t+1+n);
h=unique(t+1,t+n+1)-(t+1);
for(reg int i=1;i<=n;i++) {
int tt=a[i];
a[i]=lower_bound(t+1,t+h+1,a[i])-t; ff[a[i]]=tt;//离散化
v[a[i]].push_back(i);
}
for(reg int i=1;i<=pos[n];i++){
clear(cnt,h); pa mode=make_pair(N,0); //first 为众数的值 ,second 为众数的个数
for(reg int j=i;j<=pos[n];j++){//
for(reg int k=(j-1)*m+1;k<=j*m;k++){
cnt[ a[k] ]++;
if(cnt[a[k]] >mode.second||(cnt[ a[k] ]== mode.second && a[k]<mode.first)) mode=make_pair(a[k],cnt[a[k]]);
}
f[i][j]=mode;
}
}
for(reg int i=1,l,r;i<=n;i++){
l=rd();r=rd();
printf("%d\n",ff[query(l,r)]);
}
return 0;
}