题解:P13984 数列分块入门 9
一般来说维护这类神奇东西的题目都可以用莫队来做。
不会莫队的可以去 OI Wiki 上看看。
考虑莫队,加入一个数的时候应该怎么做。
设
那删除呢?
当然,一种比较简单的思路是直接用回滚莫队,完全没有思维难度,这里介绍另一种方法——值域分块。
我们对值域进行分块,记
然后得到了最小众数的出现次数后,要得到最小众数,我们先对每个值域块扫过去,取
//码风略丑,谨慎观看
#include <bits/stdc++.h>
using namespace std;
inline long long read(void) {
long long x = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - 48, c = getchar();
return x * f;
}
struct node {
long long l, r, id;
} query[300005];
long long n, k = 600, cl = 1, cr = 0, qwq[300005], a[300005], s[300005], ans[300005], buc1[1000], buc2[300005], buc3[505][300005], cnt;
map<long long, long long> mp;
bool cmp (node x, node y) {
if (qwq[x. l] == qwq[y. l]) return (qwq[x. l] & 1) ? (x. r < y. r) : (x. r > y. r);
return x. l < y. l;
}
int main(void) {
n = read();
for (int i = 1; i <= 300000; i++) qwq[i] = (i - 1) / k + 1;
for (int i = 1; i <= n; i++) a[i] = s[i] = read();
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n; i++) if (!mp[s[i]]) mp[s[i]] = ++cnt, s[cnt] = s[i];
for (int i = 1; i <= n; i++) a[i] = mp[a[i]];
for (int i = 1; i <= n; i++) query[i]. l = read(), query[i]. r = read(), query[i]. id = i;
sort(query + 1, query + 1 + n, cmp);
for (int i = 1; i <= n; i++) {
while (cr < query[i]. r) {
cr++;
buc3[qwq[a[cr]]][buc2[a[cr]]]--;
buc2[a[cr]]++;
buc3[qwq[a[cr]]][buc2[a[cr]]]++;
buc1[qwq[a[cr]]] = max(buc1[qwq[a[cr]]], buc2[a[cr]]);
}
while (cl > query[i]. l) {
cl--;
buc3[qwq[a[cl]]][buc2[a[cl]]]--;
buc2[a[cl]]++;
buc3[qwq[a[cl]]][buc2[a[cl]]]++;
buc1[qwq[a[cl]]] = max(buc1[qwq[a[cl]]], buc2[a[cl]]);
}
while (cl < query[i]. l) {
if (buc1[qwq[a[cl]]] == buc2[a[cl]] && buc3[qwq[a[cl]]][buc2[a[cl]]] == 1) buc1[qwq[a[cl]]]--;
buc3[qwq[a[cl]]][buc2[a[cl]]]--;
buc2[a[cl]]--;
buc3[qwq[a[cl]]][buc2[a[cl]]]++;
cl++;
}
while (cr > query[i]. r) {
if (buc1[qwq[a[cr]]] == buc2[a[cr]] && buc3[qwq[a[cr]]][buc2[a[cr]]] == 1) buc1[qwq[a[cr]]]--;
buc3[qwq[a[cr]]][buc2[a[cr]]]--;
buc2[a[cr]]--;
buc3[qwq[a[cr]]][buc2[a[cr]]]++;
cr--;
}
long long nnn = 1;
for (int j = 2; j <= qwq[300000]; j++) if (buc1[j] > buc1[nnn]) nnn = j;
for (int j = (nnn - 1) * k + 1; j <= nnn * k; j++)
if (buc2[j] == buc1[nnn]) {
ans[query[i]. id] = j;
break;
}
}
for (int i = 1; i <= n; i++) printf("%lld\n", s[ans[i]]);
return 0;
}