洛谷 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)]);
    }
}