#include <iostream> // For cin, cout
#include<cassert>
#include <vector> // For vector container
#include <tuple> // For tuple
#include <random> // For mt19937 and uniform_int_distribution
#include <chrono> // For timing
#include <algorithm> // For swap
#include <cstdint> // For int64_t if needed
using namespace std;
using namespace chrono;
// ===================== Configuration =====================
#define VALUE uint64_t
#define MAXN 200001
#define LSB(x) ((x) & -(x))
#define PARENT(x) ((x) + LSB(x))
#define LEFT_SIBLING(x) ((x) - LSB(x))
const int LOGN = 18;
// ===================== Global Arrays =====================
VALUE point[MAXN];
VALUE tree[MAXN];
VALUE lazy[MAXN];
bool has_lazy[MAXN];
int n_fenwick;
// ===================== Macros for Combine =====================
#define combine_value(a, b) ((a) + (b))
#define DEFAULT_COMBINE (0)
// ===================== Core Functions =====================
bool update_point(int nd, int v) {
point[nd] += v;
tree[nd] += v;
// smart move to update parent
// the node is not dirty so we return false
return false;
}
void update_interval(int nd, VALUE value) {
has_lazy[nd] = 1;
lazy[nd] += value;
tree[nd] += value * 1ll * LSB(nd);
point[nd] += value;
}
#define foreach_fenwick_children(child, nd) \
for (int sibling = LEFT_SIBLING(nd), child = (nd) - 1; child > sibling; child -= LSB(child))
void push_lazy(int nd) {
if (nd > n_fenwick) return;
if (!has_lazy[nd]) return;
foreach_fenwick_children(child, nd) {
update_interval(child, lazy[nd]);
}
has_lazy[nd] = false;
lazy[nd] = 0;
}
int go_up(int lo, int hi, int* record) {
int cnt = 0;
while (lo < hi) {
record[cnt++] = lo;
lo = PARENT(lo);
}
return cnt;
}
void pull_lazy(int lo, int hi) {
static int parent[LOGN];
int cnt = go_up(PARENT(lo), hi, parent);
while (cnt--) {
push_lazy(parent[cnt]);
}
}
void combine(int nd) {
if (nd > n_fenwick) return;
tree[nd] = point[nd];
foreach_fenwick_children(chld, nd) {
tree[nd] = combine_value(tree[chld], tree[nd]);
}
}
void recalculate(int lo, int hi) {
while (lo < hi) {
combine(lo);
lo = PARENT(lo);
}
}
#define fenwick_range_iter(l, r, i, i_point) for (int i = (r), next_r, i_point;(l) <= i && (next_r = LEFT_SIBLING(i), (i_point = (next_r < (l) - 1)), true);i = (i_point ? i - 1 : next_r))
// ===================== Update / Query =====================
void range_update_fenwick(int l, int r, int v) {
int previous_node = 0;
int first_point = 0;
bool node_dirty = false;
pull_lazy(r, n_fenwick + 1);
fenwick_range_iter(l, r, i, i_point) {
if (i_point) {
node_dirty = update_point(i, v);
if (first_point == 0) first_point = i;
if (l != i || node_dirty) push_lazy(i);
} else {
update_interval(i, v);
node_dirty = false;
}
previous_node = i;
}
recalculate(PARENT(r), PARENT(first_point ? first_point : previous_node));
recalculate(node_dirty ? previous_node : PARENT(previous_node),
n_fenwick + 1);
}
VALUE range_query_fenwick(int l, int r) {
assert(l <= r);
VALUE ans;
bool empty = true;
pull_lazy(r, n_fenwick + 1);
fenwick_range_iter(l, r, i, i_point) {
const VALUE& segment = i_point ? point[i] : tree[i];
ans = empty ? segment : combine_value(segment, ans);
empty = false;
if (i_point && l != i) {
push_lazy(i);
}
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
n_fenwick = 50000; // size for testing
int Q = 20000; // number of random operations
// Initialize Fenwick tree and brute-force array
fill(point, point + n_fenwick + 1, 0);
fill(tree, tree + n_fenwick + 1, 0);
fill(lazy, lazy + n_fenwick + 1, 0);
fill(has_lazy, has_lazy + n_fenwick + 1, false);
vector<VALUE> brute(n_fenwick + 1, 0);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<int> dist_index(1, n_fenwick);
uniform_int_distribution<int> dist_value(1, 100000);
int errors = 0;
for (int q = 0; q < Q; ++q) {
int l = dist_index(rng);
int r = dist_index(rng);
if (l > r) swap(l, r);
if (rng() % 2 == 0) {
// Range update
int val = dist_value(rng);
range_update_fenwick(l, r, val);
for (int i = l; i <= r; ++i) brute[i] += val;
} else {
// Range query
VALUE fenwick_ans = range_query_fenwick(l, r);
VALUE brute_ans = 0;
for (int i = l; i <= r; ++i) brute_ans += brute[i];
cout << "Query [" << l << "," << r << "] "
<< "Fenwick=" << fenwick_ans << " Brute=" << brute_ans << "\n";
if (fenwick_ans != brute_ans) {
throw "mismatch";
}
}
}
if (errors == 0)
cout << "All tests passed!\n";
else
cout << errors << " errors found.\n";
return 0;
}
https://www.spoj.com/problems/GSS1/
Classic segment tree problem solved using Fenwick tree.
Please ignore the fast int code. Performance comparable to segment tree.
The basic idea is to cover a range [left, right] we need at max log square powers of two.
Keep removing all powers of two from right until we reach left value. If we cant remove a power we can always decrease by 1.
If mergeing two consecutive segment is constant time. Whole range only take log square.
I visited sereja and brackets after ten years.
It's running much faster than segment tree.
https://mirror.codeforces.com/problemset/problem/380/C
As always as the whole picture becomes clearer, the code is always getting shorter lol.
Trying to get nails for my new hammer. Let's keep hammering.