1. 程式人生 > 其它 >LOJ6285. 數列分塊入門 9 - 離線區間眾數 -- 回滾莫隊

LOJ6285. 數列分塊入門 9 - 離線區間眾數 -- 回滾莫隊

LOJ6285. 數列分塊入門 9 - 離線區間眾數 -- 回滾莫隊

最近正在通過這個這個題集學習分塊,做到最後一題求區間眾數的時候百思不得其解,無奈去網上搜索題解。在搜尋的過程中,許多部落格都提到了一種叫做回滾莫隊的演算法,於是又去花了半天時間學習新技術,終於用回滾莫隊來做出了這道題

題目連結 : #6285. 數列分塊入門 9 - 題目 - LibreOJ (loj.ac)

回滾莫隊學習參考資料 :『回滾莫隊及其簡單運用』


程式碼

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
const int maxn = 1e5;
struct Query {
	int l, r, id;
}q[maxn+10];
int a[maxn + 10];
int st[maxn + 10];
int ed[maxn + 10];
int bel[maxn + 10];

void init(int n) {
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	int sq;
	sq = sqrt(n);
	for (int i = 1; i <= n; i++) {
		st[i] = n / sq * (i - 1) + 1;
		ed[i] = n / sq * i;
	}
	ed[sq] = n;
	for (int i = 1; i <= sq; i++) {
		for (int j = st[i]; j <= ed[i]; j++) {
			bel[j] = i;
		}
	}
}
bool cmp(Query a, Query b) {
	if (bel[a.l] != bel[b.l])
		return bel[a.l] < bel[b.l];
	else
		return a.r < b.r;
}
int ans[maxn + 10];
unordered_map<int, int> cnt1;
void add(int p, int& ans) {
	cnt1[a[p]]++;
	if (cnt1[a[p]] > cnt1[ans])
		ans = a[p];
	else if (cnt1[a[p]] == cnt1[ans])
		ans = min(a[p], ans);
}
void del(int p) {
	cnt1[a[p]]--;
}
void solve() {
	int n;
	cin >> n;
	init(n);
	for (int i = 1; i <= n; i++) {
		cin >> q[i].l >> q[i].r;
		q[i].id = i;
	}
	sort(q + 1, q + 1 + n, cmp);
	int l = 1, r = 0;
	int curblo = 0;
	int Max = 0;
	for (int i = 1; i <= n; i++) {
		if (bel[q[i].l] == bel[q[i].r]) {
			unordered_map<int, int> cnt2;
			for (int j = q[i].l; j <= q[i].r; j++)
				cnt2[a[j]]++;
			int t = 0;
			for (int j = q[i].l; j <= q[i].r; j++)
				if (cnt2[a[j]] > cnt2[t])
					t = a[j];
				else if (cnt2[a[j]] == cnt2[t])
					t = min(a[j], t);
			ans[q[i].id] = t;
			continue;
		}
		if (curblo != bel[q[i].l]) {
			while (r > ed[bel[q[i].l]])
				del(r--);
			while (l < ed[bel[q[i].l]] + 1)
				del(l++);
			Max = 0;
			curblo = bel[q[i].l];
		}
		while (r < q[i].r)
			add(++r, Max);
		int t = Max;
		int l2 = l;
		while (l2 > q[i].l)
			add(--l2, t);
		ans[q[i].id] = t;
		while (l2 < l)
			del(l2++);
	}
	for (int i = 1; i <= n; i++) {
		cout << ans[i] << '\n';
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	solve();
	return 0;
}