个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客
要求实现区间求和,区间异或
对每个二进制位维护一棵线段树,实现区间异或可以通过对该位求补集大小实现
洛谷传送门:CF242E XOR on Segment - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
要求实现区间求和,区间异或。
观察异或性质:一个区间异或 0 0 0后所有元素保持不变;一个区间异或 1 1 1后所有元素取反。
那么我们就得到了思路:线段树维护区间反转即可。对于待异或的数字,我们分别取出每一位,如果是 1 1 1,那么我我们就对区间进行反转即可。
对每个二进制位维护一棵线段树,实现区间异或可以通过对该位求补集大小实现。
#include
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e5 + 10, MOD = 1e14 + 7;
int a[N], ans[30];
int binpow(int x, int y, int mod = MOD, int res = 1){
for (; y; y >>= 1, (x *= x) %= mod) if (y & 1) (res *= x) %= mod;
return res;
}
namespace SegTree{
#define ls rt << 1
#define rs rt << 1 | 1
#define lson ls, id, l, mid
#define rson rs, id, mid + 1, r
int tree[N << 2][22], lazy[N << 2][22];
inline void push_up(int rt, int id){ tree[rt][id] = tree[ls][id] + tree[rs][id]; }
inline void push_down(int rt, int id, int m){
if(!lazy[rt][id]) return;
lazy[ls][id] ^= lazy[rt][id], lazy[rs][id] ^= lazy[rt][id];
tree[ls][id] = (m - (m >> 1)) - tree[ls][id];
tree[rs][id] = (m >> 1) - tree[rs][id];
lazy[rt][id] = 0;
}
void build(int rt, int id, int l, int r){
lazy[rt][id] = 0;
if(l == r){
tree[rt][id] = ((a[l] >> id) & 1);
return;
}
int mid = l + r >> 1;
build(lson), build(rson);
push_up(rt, id);
}
void update(int rt, int id, int l, int r, int L, int R){
if(l >= L && r <= R){
tree[rt][id] = (r - l + 1) - tree[rt][id];
lazy[rt][id] ^= 1;
return;
}
push_down(rt, id, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update(lson, L, R);
if(mid < R) update(rson, L, R);
push_up(rt, id);
}
int query(int rt, int id, int l, int r, int L, int R){
if(l >= L && r <= R) return tree[rt][id];
push_down(rt, id, r - l + 1);
int mid = l + r >> 1, ans = 0;
if(mid >= L) ans += query(lson, L, R);
if(mid < R) ans += query(rson, L, R);
return ans;
}
}
inline void solve(){
int n = 0; cin >> n;
memset(ans, 0, sizeof(ans));
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 0; i < 22; i++) SegTree::build(1, i, 1, n);
//for(int i = 0; i < 22; i++) cout << "# i = " << i << ", bit_count = " << SegTree::get_bit_cnt(i) << endl;
int q = 0; cin >> q;
while(q--){
int op, l, r; cin >> op >> l >> r;
if(op == 1){
int ans = 0;
for(int i = 0; i < 22; i++){
int bitcnt = SegTree::query(1, i, 1, n, l, r);
if(bitcnt) ans += bitcnt * binpow(2, i);
}
cout << ans << endl;
} else {
int x; cin >> x;
for(int i = 0; i < 22; i++){
if((x >> i) & 1) SegTree::update(1, i, 1, n, l, r);
}
}
}
}
signed main(){
ios_base::sync_with_stdio(false), cin.tie(0);
cout << fixed << setprecision(12);
int t = 1; //cin >> t;
while(t--) solve();
return 0;
}