紅球進黑洞【線段樹區間更新+二進位制異或處理】【牛客小白月賽9-C】
阿新 • • 發佈:2018-11-20
題目連結
給你N個點,M次查詢,問的是(一)、區間【l, r】的數的總和;(二)、把區間【l, r】上的所有點去異或(xor)一個數X。
一開始用了點更新,然後T了,想了一會,最後在比賽結束前終於美滋滋的完成了AC,慶幸,我的想法是這樣的,將每個點的值用一個另開的[22]位二進位制來存。放心,22位是絕對夠的,然後向上更新的是每一位的個數和。這樣,就能保證線段樹區間更新的速率了。
具體看一下程式碼(學院派還是很好懂的)
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 100005; int N, M, op, L, R, Xi; ll tree[maxN<<2][25], lazy[maxN<<2], ans; void pushup(int rt) { for(int i=0; i<22; i++) { tree[rt][i] = tree[rt<<1][i] + tree[rt<<1|1][i]; } } void buildTree(int rt, int l, int r) { lazy[rt] = 0; if(l == r) { ll x; scanf("%lld", &x); for(int i=0; i<22; i++) { if( ((x>>i)&1) ) tree[rt][i] = 1; else tree[rt][i] = 0; } return; } int mid = (l + r)>>1; buildTree(rt<<1, l, mid); buildTree(rt<<1|1, mid+1, r); pushup(rt); } void pushdown(int rt, int l, int r) { int mid = (l + r)>>1; if(lazy[rt]) { lazy[rt<<1|1] = lazy[rt<<1|1]^lazy[rt]; lazy[rt<<1] = lazy[rt<<1]^lazy[rt]; for(int i=0; i<22; i++) { int tmp = ( ((lazy[rt]>>i)&1) ); if(tmp) { tree[rt<<1][i] = mid-l+1-tree[rt<<1][i]; tree[rt<<1|1][i] = r-mid-tree[rt<<1|1][i]; } } lazy[rt] = 0; } } void update(int rt, int l, int r, int ql, int qr, int val) { int mid = (l + r)>>1; if(ql<=l && qr>=r) { lazy[rt] = (lazy[rt]^val); for(int i=0; i<22; i++) { int tmp = ( (val>>i)&1 ); if(tmp == 1) { tree[rt][i] = r-l+1-tree[rt][i]; } } return; } pushdown(rt, l, r); if(ql>mid) update(rt<<1|1, mid+1, r, ql, qr, val); else if(qr<=mid) update(rt<<1, l, mid, ql, qr, val); else { update(rt<<1|1, mid+1, r, mid+1, qr, val); update(rt<<1, l, mid, ql, mid, val); } pushup(rt); } void query(int rt, int l, int r, int ql, int qr) { int mid = (l + r)>>1; if(ql<=l && qr>=r) { for(int i=0; i<22; i++) { ans += (ll)(1<<i)*tree[rt][i]; } return; } pushdown(rt, l, r); if(ql>mid) query(rt<<1|1, mid+1, r, ql, qr); else if(qr<=mid) query(rt<<1, l, mid, ql, qr); else { query(rt<<1, l, mid, ql, mid); query(rt<<1|1, mid+1, r, mid+1, qr); } } int main() { scanf("%d%d", &N, &M); buildTree(1, 1, N); while(M--) { scanf("%d", &op); if(op == 1) { scanf("%d%d", &L, &R); ans = 0; query(1, 1, N, L, R); printf("%lld\n", ans); } else { scanf("%d%d%d", &L, &R, &Xi); update(1, 1, N, L, R, Xi); } } return 0; }