题解

luoguP4178

此题要强制在线。

首先, 对于 \(a\) 数组离散化。

再把 \(a\) 分块。

维护数组 \(cnt_{i, j}\) 表示前 \(i\) 个快 \(j\) 的出现次数。

维护数组 \(op_{i, j}\) 表示第 \(i\) ~ \(j\) 快的众数。

对于整块, 直接处理。

对于零散元素, 统计答案做比较。

如果把块长设为 \(\sqrt{n}\), 时间复杂都为 \(O((q + n) \sqrt{n})\)

#include<bits/stdc++.h>

using namespace std;

const int N = 40005;

int last, p, q, Max, now, maxx[5000][5000], cnt[5000][5000], zh, ans[N], a[N], b[N], sum[5000][N], m, n, l, r, op[N], L[N], R[N], len, T, s[5000][N], ok[N];

vector<int>g[N];

inline int query(int l, int r){
  p = op[l], q = op[r];
  Max = maxx[p + 1][q - 1];
  now = cnt[p + 1][q - 1];
  for(int i = l; i <= min(R[p], r); i++){
    ok[a[i]]++;
  }
  if(p != q){
    for(int i = L[q]; i <= r; i++){
      ok[a[i]]++;
    }
  }
  for(int i = l; i <= min(R[p], r); i++){
    zh = max(0, s[q - 1][a[i]] - s[p][a[i]]) + ok[a[i]];
    if(zh > Max || zh == Max && now > a[i]){
      now = a[i];
      Max = zh;
    }
  }
  if(p == q){
    for(int i = l; i <= r; i++){
      ok[a[i]] = 0;
    }
    return now;
  }
  for(int i = L[q]; i <= r; i++){
    zh = max(0, s[q - 1][a[i]] - s[p][a[i]]) + ok[a[i]];
    if(zh > Max || zh == Max && now > a[i]){
      now = a[i];
      Max = zh;
    }
  }
  for(int i = l; i <= min(R[p], r); i++){
    ok[a[i]] = 0;
  }
  for(int i = L[q]; i <= r; i++){
    ok[a[i]] = 0;
  }
  return now;
}

int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m;
  for(int i = 1; i <= n; ++i){
    cin >> a[i];
    b[i] = a[i];
  }
  sort(b + 1, b + n + 1);
  for(int i = 1; i <= n; ++i){
    a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
    g[a[i]].push_back(i);
  }
  len = sqrt(n);
  T = (n + len - 1) / len;
  for(int i = 1; i <= (n + len - 1) / len; ++i){
    L[i] = (i - 1) * len + 1, R[i] = min(n, i * len);
    for(int j = L[i]; j <= R[i]; j++){
      sum[i][a[j]]++;
      op[j] = i;
    }
    for(int j = 1; j <= n; ++j){
      s[i][j] = s[i - 1][j] + sum[i][j];
    }
  }
  for(int i = 1; i <= T; ++i){
    for(int j = 1; j <= n; ++j){
      ans[j] = 0;
    }
    now = 0, Max = -1;
    for(int j = i; j <= T; ++j){
      for(int k = L[j]; k <= R[j]; k++){
        ans[a[k]]++;
        if(ans[a[k]] > Max || ans[a[k]] == Max && a[k] < now){
          Max = ans[a[k]], now = a[k];
        }
      }
      cnt[i][j] = now;
      maxx[i][j] = Max;
    }
  }
  while(m--){
    cin >> l >> r;
    l = (l + last - 1) % n + 1;
    r = (r + last - 1) % n + 1;
    if(l > r){
      swap(l, r);
    }
    cout << (last = b[query(l, r)]) << '\n';
  }
  return 0;
}
posted @ 2024-04-23 16:09  liuyichen  阅读(0)  评论(0编辑  收藏  举报