*题解:P13984 数列分块入门 9
解析
根据题目名称,先将数列分块。那么如何才能知道 \([l,r]\) 之间的众数?对于中间的整块,我们希望知道它们并起来之后的众数,因为这个看起来很接近答案并且可以用 \(O(n\cdot \frac{n}{B})\) 的复杂度大力预处理出来,\(B\) 为块长。然后讨论众数位于旁边散段的情况,用 vector 预处理出每个数的所有位置,二分统计散段中每个数在区间内出现次数即可。
需要离散化。时间复杂度 \(O(n\cdot \dfrac{n}{B} +nB\log n)\)。
代码
这里块长取了 \(\sqrt n\)。注意常数。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 3e5 + 5,B = 550;
int a[N],b[N];
vector<int> pos[N],val;
pii w[N / B + 5][N / B + 5];
int t[N];
int cnt,num[N],lp[N / B + 5],rp[N / B + 5];
int vis[N];
void build(int n){
while(cnt * B + 1 <= n){
cnt++;
lp[cnt] = (cnt - 1) * B + 1;
rp[cnt] = cnt * B;
if(rp[cnt] > n){
rp[cnt] = n;
break;
}
}
for(int i=1;i<=cnt;i++){
for(int j=lp[i];j<=rp[i];j++){
num[j] = i;
}
}
}
int get(int x){
return lower_bound(val.begin(),val.end(),x) - val.begin();
}
int vist;
pii calc(int l,int r,int l2,int r2){
vist++;
int mxc = 0,mnv = 0;
for(int i=l;i<=r;i++){
int p = b[i];
if(vis[p] == vist) continue;
vis[p] = vist;
int lb = lower_bound(pos[p].begin(),pos[p].end(),l2) - pos[p].begin(),rb = upper_bound(pos[p].begin(),pos[p].end(),r2) - pos[p].begin() - 1;
int x = rb - lb + 1;
if(x > mxc){
mxc = x;
mnv = a[i];
}else if(x == mxc && a[i] < mnv){
mnv = a[i];
}
}
return make_pair(mnv,mxc);
}
void upd(pii &res,pii x){
if(x.second > res.second){
res.second = x.second;
res.first = x.first;
}else if(x.second == res.second && x.first < res.first){
res.first = x.first;
}
}
int read(){
char ch = getchar();
int a = 1,x = 0;
while(ch < '0' || ch > '9'){
if(ch == '-') a = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return a * x;
}
signed main(){
// ios::sync_with_stdio(false);
// cin.tie(0),cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n = read();
build(n);
for(int i=1;i<=n;i++){
a[i] = read();
val.push_back(a[i]);
}
sort(val.begin(),val.end());
val.erase(unique(val.begin(),val.end()),val.end());
for(int i=1;i<=n;i++){
b[i] = get(a[i]);
pos[b[i]].push_back(i);
}
for(int i=1;i<=cnt;i++){
memset(t,0,val.size() * sizeof(int));
for(int k=i;k<=cnt;k++){
w[i][k] = w[i][k - 1];
for(int j=lp[k];j<=rp[k];j++){
int p = b[j];
t[p]++;
upd(w[i][k],make_pair(a[j],t[p]));
}
}
}
for(int i=1;i<=n;i++){
int l = read(),r = read();
if(num[l] == num[r]){
pii res = calc(l,r,l,r);
cout<<res.first<<'\n';
continue;
}
pii res = w[num[l] + 1][num[r] - 1];
pii lv = calc(l,rp[num[l]],l,r),rv = calc(lp[num[r]],r,l,r);
upd(res,lv);
upd(res,rv);
cout<<res.first<<'\n';
}
return 0;
}

浙公网安备 33010602011771号