-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmo.cpp
134 lines (112 loc) · 3.27 KB
/
mo.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//
// Mo のアルゴリズム
//
// reference:
// ei1333: Mo's algorithm
// https://ei1333.hateblo.jp/entry/2017/09/11/211011
//
// verified:
// SPOJ FREQUENT - Frequent values
// https://www.spoj.com/problems/FREQUENT/
//
/*
平方分割に基づいた、区間クエリに対する一般的なテク
・クエリ先読みができる、区間更新はなし
・区間の左端や右端を 1 個ずたしたものに対する値を高速に求められる (区間に a[idx] の要素を加えたり除いたり)
ここでは
cnt[i] := i が何個あるか
hist[c] := 区間内に c 個ある値が何種類あるか
num_kind := 区間内に何種類の数があるか
mode := 最頻値の出現回数
*/
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
// Mo
struct Mo {
vector<int> left, right, index; // the interval's left, right, index
vector<bool> v;
int window;
int nl, nr, ptr;
Mo(int n) : window((int)sqrt(n)), nl(0), nr(0), ptr(0), v(n, false) { }
/* push */
void push(int l, int r) { left.push_back(l), right.push_back(r); }
/* sort intervals */
void build() {
index.resize(left.size());
iota(index.begin(), index.end(), 0);
sort(begin(index), end(index), [&](int a, int b)
{
if(left[a] / window != left[b] / window) return left[a] < left[b];
return right[a] < right[b];
});
}
/* extend-shorten */
void extend_shorten(int id) {
v[id].flip();
if (v[id]) insert(id);
else erase(id);
}
/* next id of interval */
int next() {
if (ptr == index.size()) return -1;
int id = index[ptr];
while (nl > left[id]) extend_shorten(--nl);
while (nr < right[id]) extend_shorten(nr++);
while (nl < left[id]) extend_shorten(nl++);
while (nr > right[id]) extend_shorten(--nr);
return index[ptr++];
}
/* insert, erase (to be set appropriately) */
void insert(int id);
void erase(int id);
};
//------------------------------//
// Examples
//------------------------------//
const int GETA = 100000;
int N, Q;
int A[100100], res[100100];
int cnt[200100], hist[100100];
int num_kind = 0, mode = 0;
void Mo::insert(int id) {
int val = A[id];
if (cnt[val] == 0) ++num_kind;
--hist[cnt[val]];
++cnt[val];
++hist[cnt[val]];
mode = max(mode, cnt[val]);
}
void Mo::erase(int id) {
int val = A[id];
--hist[cnt[val]];
if(cnt[val] == mode && hist[cnt[val]] == 0) --mode;
--cnt[val];
++hist[cnt[val]];
if (cnt[val] == 0) --num_kind;
}
int main() {
while (scanf("%d", &N), N) {
memset(cnt, 0, sizeof(cnt));
memset(hist, 0, sizeof(hist));
mode = 0;
scanf("%d", &Q);
for(int i = 0; i < N; i++) {
scanf("%d", &A[i]);
A[i] += GETA;
}
Mo mo(N);
for(int i = 0; i < Q; i++) {
int x, y;
scanf("%d %d", &x, &y);
mo.push(--x, y);
}
mo.build();
for(int i = 0; i < Q; i++) res[mo.next()] = mode;
for(int i = 0; i < Q; i++) printf("%d\n", res[i]);
}
}