莫队
莫队
1、时间复杂度为 \(O(n\sqrt n)\),用于离线处理一些操作的答案。
template<typename T>
struct Md{
struct Q {
int L;
int R;
int num;
};
int n, m, k, len, l, r;
T res;
vector<Q> rs;
vector<T> a, ans, pos, cnt;
Md(int n_, int m_, int len_, int k_) : a(n_ + 1), ans(m_ + 1), pos(n_ + 1), cnt(k_ + 1) {
l = 1;
r = res = 0;
n = n_;
m = m_;
len = len_;
k = k_;
init();
action();
}
inline void init() {
for (int i = 1; i <= n; i++) {
cin >> a[i];
pos[i] = (i - 1) / len + 1;
}
for (int i = 1; i <= m; i++) {
int l, r;
cin >> l >> r;
rs.push_back({l, r, i});
}
sort(rs.begin(), rs.end(), [&](auto &x, auto &y) {
return pos[x.L] == pos[y.L]
? (x.R == y.R ? 0 : (pos[x.L] & 1) ^ (x.R < y.R))
: x.L < y.L;
});
}
inline void add(int x) {
cnt[a[x]]++; res += cnt[a[x]] * 2 - 1;
}
inline void sub(int x) {
cnt[a[x]]--; res -= cnt[a[x]] * 2 + 1;
}
inline void action() {
for (auto [L, R, num] : rs) {
while (L < l) add(--l);
while (R > r) add(++r);
while (L > l) sub(l++);
while (R < r) sub(r--);
ans[num] = res;
}
}
inline void print_ans() {
for (int i = 1; i <= m; i++) cout << ans[i] << '\n';
}
};
void solve() {
int n, m, k;
read(n, m, k);
int len = sqrt(n);
Md<i64> t(n, m, len, k);
t.print_ans();
}
带修莫队
1、时间复杂度为 \(O(n^\frac{5}{3})\)。
template<typename T>
struct Cmd{
struct Q {
int L, R, num, tnum;
};
struct time_ {
int pos, x;
};
int n, m, len, k, l, r, last;
T res;
vector<Q> rs;
vector<time_> ts;
vector<T> a, ans, mp;
Cmd(int n_, int m_, int len_, int k_) : a(n_ + 1), ans(m_ + 1), mp(k_ + 1) {
n = n_;
m = m_;
len = len_;
k = k_;
ts.push_back({0, 0});
l = 1;
r = res = last = 0;
init();
action();
}
inline void add(int x) {
if (!(mp[x]++)) {
res++;
}
}
inline void sub(int x) {
if (!(--mp[x])) {
res--;
}
}
inline void update(int opt) {
if (opt == 1) {
last++;
}
if (ts[last].pos >= l && ts[last].pos <= r) {
add(ts[last].x);
sub(a[ts[last].pos]);
}
swap(ts[last].x, a[ts[last].pos]);
if (opt == 0) last--;
}
inline void init() {
for (int i = 1; i <= n; i++) read(a[i]);
for (int i = 1; i <= m; i++) {
int L, R;
char opt;
cin >> opt;
read(L, R);
if (opt == 'Q') rs.push_back({L, R, (int)rs.size() + 1, (int)ts.size() - 1});
else ts.push_back({L, R});
}
sort(rs.begin(), rs.end(), [&] (const auto &x, const auto &y) {
if (x.L / len != y.L / len)
return x.L / len > y.L / len;
else if (x.R / len != y.R / len)
return x.R / len > y.R / len;
else
return x.tnum > y.tnum;
});
}
inline void action() {
for (auto [L, R, num, tnum] : rs) {
while (L < l) add(a[--l]);
while (R > r) add(a[++r]);
while (L > l) sub(a[l++]);
while (R < r) sub(a[r--]);
while (last < tnum) update(1);
while (last > tnum) update(0);
ans[num] = res;
}
}
inline void print_ans() {
for (int i = 1; i <= rs.size(); i++)
cout << ans[i] << '\n';
}
};
void solve() {
int n, m;
read(n, m);
int len = powl(n, 2.0 / 3.0);
Cmd<int> t(n, m, len, 1e6);
t.print_ans();
}
还有些回滚莫队等等一些莫队算法会持续更新...

浙公网安备 33010602011771号