Eterna_King

导航

P4168 [Violet]蒲公英

神仙分块题?其实还是很简单的,res[i][j]表示第i块到第j块的众数,然后再用sum[i][j]表示前i块中j这个种类出现的次数,然后分块瞎搞就行了,感觉我写的十分简洁,好评(

//author Eterna
#define Hello the_cruel_world!
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<utility>
#include<cmath>
#include<climits>
#include<deque>
#include<functional>
#include<complex>
#include<numeric>
#include<unordered_map>
#define Pi acos(-1.0)
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
#define pb(x) push_back(x)
#define lowbit(x) (x & -x)
#define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin)
#define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define outd(x) printf("%d\n", x)
#define outld(x) printf("%lld\n", x)
#define il inline
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 4e4;
const int maxm = 2e2;
const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const double eps = 1e-7;
inline int read_int() {
    char c;
    int ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
inline ll read_ll() {
    char c;
    ll ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
int res[maxm + 5][maxm + 5], sum[maxm + 5][maxn + 5], cnt[maxn + 5];
int block, arr[maxn + 5], ID[maxn + 5];
int n, q, last;
int m, pos[maxn + 5];
void pre_init() {
    for (int i = 1; i <= n; ++i)++sum[ID[i]][arr[i]];
    for (int i = 1; i <= m; ++i)for (int j = 1; j <= ID[n]; ++j)sum[j][i] += sum[j - 1][i];
    for (int i = 1; i <= ID[n]; ++i) {
        memset(cnt, 0, sizeof(cnt));
        for (int j = (i - 1) * block + 1; j <= n; ++j) {
            int p = arr[j], k = res[i][ID[j - 1]];
            ++cnt[p];
            if (cnt[p] > cnt[k])res[i][ID[j]] = p;
            else if (cnt[p] == cnt[k] && p < k)res[i][ID[j]] = p;
            else res[i][ID[j]] = k;
        }
    }
    memset(cnt, 0, sizeof(cnt));
}
int Query(int L, int R) {
    int ans = res[ID[L] + 1][ID[R] - 1], tot = max(0, sum[ID[R] - 1][ans] - sum[ID[L]][ans]);
    for (int i = L; i <= min(ID[L] * block, R); ++i) {
        int p = arr[i];
        ++cnt[p];
        int s = cnt[p] + max(0, (sum[ID[R] - 1][p] - sum[ID[L]][p]));
        if (s > tot) ans = p, tot = s;
        else if (s == tot && p < ans)ans = p;
    }
    if (ID[L] != ID[R]) {
        for (int i = (ID[R] - 1)*block + 1; i <= R; ++i) {
            int p = arr[i];
            ++cnt[p];
            int s = cnt[p] + max(0, (sum[ID[R] - 1][p] - sum[ID[L]][p]));
            if (s > tot) ans = p, tot = s;
            else if (s == tot && p < ans)ans = p;
        }
    }
    for (int i = L; i <= min(ID[L] * block, R); ++i)--cnt[arr[i]];
    if (ID[L] != ID[R])for (int i = (ID[R] - 1) * block + 1; i <= R; ++i)--cnt[arr[i]];
    return ans;
}
int main()
{
    n = read_int(), q = read_int();
    block = ceil(sqrt(n));
    for (int i = 1; i <= n; ++i) pos[i] = arr[i] = read_int(), ID[i] = (i - 1) / block + 1;
    sort(pos + 1, pos + 1 + n);
    m = unique(pos + 1, pos + 1 + n) - pos - 1;
    for (int i = 1; i <= n; ++i)arr[i] = lower_bound(pos + 1, pos + 1 + m, arr[i]) - pos;
    pre_init();
    for (int i = 1; i <= q; ++i) {
        int l = read_int(), r = read_int();
        l = (l + last - 1) % n + 1, r = (r + last - 1) % n + 1;
        if (l > r)swap(l, r);
        last = pos[Query(l, r)];
        outd(last);
    }
    return 0;
}

 

posted on 2019-03-19 12:05  Eterna_King  阅读(132)  评论(0编辑  收藏  举报