#include #include #define all(x) (x).begin(), (x).end() // author: @noisegain using namespace std; const int K = 1288; // eq sqrt(nlogn) where n = 10^5 // because of O(sqrt(n * log(n))) instead of O(sqrt(n) * log(n)) // [L; R) invariant for all type of queries and variables struct sqrt_decompose { vector> a; vector> blocks; vector promise; int changes = 0; int n; explicit sqrt_decompose(const vector &init) { n = init.size(); a.push_back(init); rebuild(); } void rebuild() { vector init; init.reserve(n); for (auto &x : a) { init.insert(init.end(), x.begin(), x.end()); } a.clear(); blocks.clear(); changes = 0; int size = (n + K - 1) / K; a.resize(size); blocks.resize(size); for (int i = 0; i < size; ++i) { a[i].reserve(K); blocks[i].reserve(K); } promise.resize(size, 0); for (int i = 0; i < n; ++i) { a[i / K].push_back(init[i]); blocks[i / K].push_back(init[i]); } for (auto &x : blocks) { sort(all(x)); } } void apply(int i) { blocks[i].clear(); for (auto &x : a[i]) { x += promise[i]; blocks[i].push_back(x); } promise[i] = 0; sort(all(blocks[i])); } void erase(int ind) { for (int i = 0, l = 0; i < blocks.size(); ++i) { int r = l + blocks[i].size(); if (ind < r) { auto it = lower_bound(all(blocks[i]), a[i][ind - l]); a[i].erase(a[i].begin() + (ind - l)); blocks[i].erase(it); break; } l = r; } --n; if (++changes == K) { rebuild(); } } void insert(int ind, int v) { for (int i = 0, l = 0, r; i < blocks.size(); ++i) { r = l + blocks[i].size(); if (ind <= r) { auto it = upper_bound(all(blocks[i]), v); a[i].insert(a[i].begin() + (ind - l), v); blocks[i].insert(it, v); break; } l = r; } ++n; if (++changes == K) { rebuild(); } } void update(int l_q, int r_q, int x) { for (int i = 0, l = 0, r; i < blocks.size(); i++, l = r) { r = l + blocks[i].size(); if (r <= l_q || r_q <= l) { continue; } if (l >= l_q && r <= r_q) { promise[i] += x; continue; } for (int j = max(l, l_q); j < min(r, r_q); ++j) { a[i][j - l] += x; } apply(i); } } int get(int l_q, int r_q, int x, int y) { int l = 0, r, cnt = 0; for (int i = 0; i < blocks.size(); ++i, l = r) { r = l + blocks[i].size(); int nx = x - promise[i]; int ny = y - promise[i]; if (r <= l_q || r_q <= l) { continue; } if (l >= l_q && r <= r_q) { cnt += static_cast(upper_bound(all(blocks[i]), ny) - lower_bound(all(blocks[i]), nx)); continue; } for (int j = max(l, l_q); j < min(r, r_q); ++j) { if (a[i][j - l] <= ny && a[i][j - l] >= nx) { ++cnt; } } } return cnt; } };