*题解: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;
}
posted @ 2026-05-14 21:45  yutar  阅读(7)  评论(0)    收藏  举报