#include <bits/stdc++.h>
using namespace std;
struct LazySegmentTree {
const int LOGMAX = 30;
int n;
vector<int> lazy;
vector<vector<int>> sum;
vector<int> L, R;
LazySegmentTree(vector<int>& arr) {
int sz = arr.size();
n = 1;
while (n < sz) n <<= 1;
lazy.assign(2 * n, 0);
sum.assign(2 * n, vector<int>(LOGMAX, 0));
L.assign(2 * n, 0);
R.assign(2 * n, 0);
// Initialize the segment tree leaves
for (int i = 0; i < sz; ++i) {
for (int k = 0; k < LOGMAX; ++k) {
sum[i + n][k] = (arr[i] >> k) & 1;
}
}
for(int i = 0; i < n; ++i){
L[i + n] = R[i + n] = i;
}
// Build the segment tree
for (int i = n - 1; i > 0; --i) {
for (int k = 0; k < LOGMAX; ++k) {
sum[i][k] = sum[2 * i][k] + sum[2 * i + 1][k];
}
L[i] = L[2 * i];
R[i] = R[2 * i + 1];
}
}
void apply(int node, int x) {
for (int k = 0; k < LOGMAX; ++k) {
if (x & (1 << k)) {
sum[node][k] = (R[node] - L[node] + 1) - sum[node][k];
}
}
if (node < n) {
lazy[node] ^= x;
}
}
void propagate(int node) {
if (lazy[node]) {
apply(2 * node, lazy[node]);
apply(2 * node + 1, lazy[node]);
lazy[node] = 0;
}
}
void update(int node) {
for (int k = 0; k < LOGMAX; ++k) {
sum[node][k] = sum[2 * node][k] + sum[2 * node + 1][k];
}
}
void rangeUpdate(int l, int r, int x) {
l += n;
r += n;
int l0 = l, r0 = r;
// Apply any existing lazy updates
for (int i = __lg(n); i >= 1; --i) {
if ((l >> i) > 0) propagate(l >> i);
if ((r >> i) > 0) propagate(r >> i);
}
// Update the segment tree
for (; l <= r; l >>= 1, r >>= 1) {
if (l & 1) apply(l++, x);
if (!(r & 1)) apply(r--, x);
}
// Update affected parent nodes
for (l = l0 >> 1; l > 0; l >>= 1) propagate(l), update(l);
for (r = r0 >> 1; r > 0; r >>= 1) propagate(r), update(r);
}
long long rangeQuery(int l, int r) {
l += n;
r += n;
long long res = 0;
// Apply any existing lazy updates
for (int i = __lg(n); i >= 1; --i) {
if ((l >> i) > 0) propagate(l >> i);
if ((r >> i) > 0) propagate(r >> i);
}
// Query the segment tree
for (; l <= r; l >>= 1, r >>= 1) {
if (l & 1) res += getSum(l++);
if (!(r & 1)) res += getSum(r--);
}
return res;
}
long long getSum(int node) {
long long result = 0;
for (int k = 0; k < LOGMAX; ++k) {
result += (1LL << k) * sum[node][k];
}
return result;
}
};
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n;
cin >> n;
vector<int> a(n + 1);
for(int i = 1; i <= n; ++i){
cin >> a[i];
}
LazySegmentTree tree(a);
int q;
cin >> q;
while(q--){
int type, l, r;
cin >> type >> l >> r;
if(type == 1){
cout << tree.rangeQuery(l, r) << '\n';
}
else{
int x;
cin >> x;
tree.rangeUpdate(l, r, x);
}
}
return 0;
}
Auto comment: topic has been updated by one_autum_leaf (previous revision, new revision, compare).
Auto comment: topic has been updated by one_autum_leaf (previous revision, new revision, compare).
$$$O(nlognloga_i)$$$
I'm pretty sure that if you build one seg tree with a node that has information for those 30 bits instead of building 30 seg trees the solution would run way faster due to cache reasons.
Yeah I think keeping the lazy as an integer which was 1 in bits that are inverted and 0 in not inverted bits works
Thanks! Fixed the code.
242E - XOR on Segment
Thanks!
Auto comment: topic has been updated by one_autum_leaf (previous revision, new revision, compare).
My code (using DNC): https://mirror.codeforces.com/contest/242/submission/292442204
thats literally a segment tree, what do you mean?
ye, but DNC ver
you should check out this problem. Its statement is in russian, but queries' descriptions are self-explanatory.