Range Subrange Middle Equal Mode Query
Description
给定序列
Limitations
Solution
视
考虑如果求出了这些组,每组对查询的贡献,其为
现在只需要求出这些组,一个暴力是二分
由于
那么复杂度
::::info[code]
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;
template<class T>
bool chmax(T &a, const T &b){
if(a < b){ a = b; return true; }
return false;
}
template<class T>
bool chmin(T &a, const T &b){
if(a > b){ a = b; return true; }
return false;
}
namespace Fastio {}
using Fastio::qin;
using Fastio::qout;
int lowbit(int x) {
return x & (-x);
}
struct Bit {
int n;
vector<i64> c1, c2;
Bit() {}
Bit(int _n): n(_n) {
c1.resize(n);
c2.resize(n);
}
void add(int x, i64 k) {
for (int i = x + 1; i <= n; i += lowbit(i)) {
c1[i - 1] += k;
c2[i - 1] += k * x;
}
}
i64 ask(int x) {
i64 res = 0;
for (int i = x + 1; i; i -= lowbit(i)) {
res += c1[i - 1] * (x + 1) - c2[i - 1];
}
return res;
}
void update(int l, int r, i64 v) {
add(l, v);
add(r + 1, -v);
}
i64 sum(int l, int r) {
return ask(r) - ask(l - 1);
}
};
struct Query {
int x, l, r, id;
Query() {}
Query(int x, int l, int r, int id) : x(x), l(l), r(r), id(id) {}
};
constexpr int B = 80, inf = 1e9;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, q;
qin >> n >> q;
vector<int> a(n), c(n), idx(n);
vector<basic_string<int>> pos(n), v(n);
for (int i = 0; i < n; i++) {
qin >> a[i], a[i]--, c[a[i]]++;
pos[a[i]] += abs(i - a[i]);
v[a[i]] += i;
idx[i] = v[a[i]].size() - 1;
}
vector<Query> qry;
for (int i = 0, l, r; i < q; i++) {
qin >> l >> r;
l--, r--;
qry.emplace_back((l + r) / 2, l, r, i);
}
vector<int> cnt;
auto init_large = [&](int x) {
cnt.assign(n, 0);
int mx = 0, flag = 0, st = 0;
for (int i = 0; x - i >= 0 && x + i < n; i++) {
chmax(mx, ++cnt[a[x - i]]);
if (i) chmax(mx, ++cnt[a[x + i]]);
if (cnt[x] == mx && !flag) st = i;
if (cnt[x] != mx && flag) qry.emplace_back(x, st, i - 1, -1);
if (cnt[x] == mx) flag = 1;
else flag = 0;
}
if (flag) qry.emplace_back(x, st, min(x, n - x - 1), -1);
};
vector<int> f(n), suf(n + 1);
auto init_small = [&](int x) {
for (int i = 0; i < n; i++) {
if (idx[i] + x < (int)v[a[i]].size()) f[i] = v[a[i]][idx[i] + x];
else f[i] = inf;
}
suf[n] = inf;
for (int i = n - 1; i >= 0; i--) suf[i] = min(suf[i + 1], f[i]);
for (int i = 0; i < n; i++)
if (c[i] < B && c[i] >= x) {
int L = pos[i][x - 1];
int R = min((c[i] > x ? pos[i][x] - 1 : inf), min(i, n - i - 1));
if (L > R) continue;
int l = L - 1, r = R;
while (l < r) {
const int mid = (l + r + 1) / 2;
if (suf[i - mid] > i + mid) l = mid;
else r = mid - 1;
}
if (l >= L) qry.emplace_back(i, L, l, -1);
}
};
for (int i = 0; i < n; i++)
if (c[i] >= B) init_large(i);
for (int i = 0; i < n; i++) sort(pos[i].begin(), pos[i].end());
for (int x = 1; x < B; x++) init_small(x);
sort(qry.begin(), qry.end(), [&](auto a, auto b) {
if (a.x != b.x) return a.x < b.x;
return a.id < b.id;
});
vector<i64> ans(q);
Bit ds(n);
for (auto it : qry) {
if (it.id != -1) ans[it.id] += ds.sum(it.l, it.r);
else ds.update(it.x - it.r, it.x - it.l, 1);
}
ds = Bit(n);
reverse(qry.begin(), qry.end());
for (auto it : qry) {
if (it.id != -1) ans[it.id] += ds.sum(it.l, it.r);
else ds.update(it.x + it.l, it.x + it.r, 1);
}
for (int i = 0; i < q; i++) qout << ans[i] << '\n';
return 0;
}