洛谷 P4168 [Violet]蒲公英
题意简述
求区间众数
题解思路
分块
代码
#include <cmath>
#include <cstdio>
#include <vector>
#include <cctype>
#include <algorithm>
#define ci const int
int n, m, last, l, r;
int a[50000];
ci ri_top = 1e7;
char ri[ri_top + 1], *rich = ri, *rr = ri;
inline void rd() {*(rr = ri + fread(rich = ri, 1, ri_top, stdin)) = 0;}
inline char nch() {if (++rich >= rr) rd(); return *rich;}
inline void read_int(int& x)
{
while (!isdigit(*rich)) nch();
for (x = *rich - '0'; isdigit(nch()); x = x * 10 + *rich - '0');
}
namespace _
{
int N, L, R, res, len, size;
bool used[50000];
struct Block
{
int l, r, ans;
int s[300], c[50000];
void add(ci& x, ci& s = 1)
{
if ((c[x] += s) > c[ans] || (c[x] == c[ans] && x < ans)) ans = x;
}
}b[300], xx;
inline int get(ci& x, ci& L, ci& R) {return b[R].c[x] - b[L - 1].c[x]; }
inline void build()
{
len = pow(n, 0.6667);
N = n / len + (bool)(n % len);
for (register int i = 0; i < N; ++i)
{
b[i].l = i * len + 1;
b[i].r = (i + 1) * len;
if (i) for (register int j = 0; j < n; ++j) b[i].c[j] = b[i - 1].c[j];
for (register int j = b[i].l; j <= b[i].r; ++j) b[i].add(a[j]);
}
b[N].r = n;
for (register int i = 0; i < N; ++i)
{
xx.ans = 0; for (register int j = 0; j < size; ++j) xx.c[j] = 0;
for (register int j = i; j < N; ++j)
{
for (register int k = b[j].l; k <= b[j].r; ++k) xx.add(a[k]);
b[i].s[j] = xx.ans;
}
}
}
inline int query(ci& l, ci& r)
{
xx.ans = 0; for (register int j = 0; j < size; ++j) xx.c[j] = 0;
L = (l - 1) / len; R = (r - 1) / len;
if (R - L <= 1)
{
for (register int i = l; i <= r; ++i) xx.add(a[i]);
return xx.ans;
}
res = b[L + 1].s[R - 1];
for (register int i = 0; i < size; ++i) used[i] = 0;
used[res] = 1;
xx.add(res, get(res, L + 1, R - 1));
for (register int i = l; i <= b[L].r; ++i)
{
if (!used[a[i]]) xx.add(a[i], get(a[i], L + 1, R - 1)), used[a[i]] = 1;
xx.add(a[i]);
}
for (register int i = b[R].l; i <= r; ++i)
{
xx.add(a[i]);
if (!used[a[i]]) xx.add(a[i], get(a[i], L + 1, R - 1)), used[a[i]] = 1;
}
return xx.ans;
}
}
std::vector < int > v;
int main()
{
read_int(n); read_int(m);
for (register int i = 1; i <= n; ++i) read_int(a[i]), v.push_back(a[i]);
std::sort(v.begin(), v.end()); v.resize(std::unique(v.begin(), v.end()) - v.begin());
for (register int i = 1; i <= n; ++i)
a[i] = std::lower_bound(v.begin(), v.end(), a[i]) - v.begin();
_::size = v.size();
_::build();
for (register int i = 1; i <= m; ++i)
{
read_int(l); read_int(r);
l = (l + last - 1) % n + 1; r = (r + last - 1) % n + 1;
if (l > r) std::swap(l, r);
printf("%d
", last = v[_::query(l, r)]);
}
}