1024 红球进黑洞 区间异或
链接:https://ac.nowcoder.com/acm/problem/19429
来源:牛客网
题目描述
在心理疏导室中有一种奇特的疏导工具,叫做红球。红球被提前分为了许多正方形小方格。
每当有人来找ATB做心理疏导时,ATB就会让他去先玩红球,然后通过红球小格方的高度来判断一个人的压力程度的高低
具体地讲,ATB会让该人对于一个序列执行以下操作
1. 区间求和,即输入l,r,输出∑i=lrxi\sum_{i=l}^{r} x_i∑i=lrxi
2. 区间异或,即输入l,r,k,对于l ≤ i ≤ r,将xi变为xi⊕kx_i \oplus kxi⊕k
可是ATB天天算计那么多答案,已经对这份工作产生了厌烦,所以请你帮帮他,对于一组给定的数据,输出对应的答案
ATB会将你感谢到爆
每当有人来找ATB做心理疏导时,ATB就会让他去先玩红球,然后通过红球小格方的高度来判断一个人的压力程度的高低
具体地讲,ATB会让该人对于一个序列执行以下操作
1. 区间求和,即输入l,r,输出∑i=lrxi\sum_{i=l}^{r} x_i∑i=lrxi
2. 区间异或,即输入l,r,k,对于l ≤ i ≤ r,将xi变为xi⊕kx_i \oplus kxi⊕k
可是ATB天天算计那么多答案,已经对这份工作产生了厌烦,所以请你帮帮他,对于一组给定的数据,输出对应的答案
ATB会将你感谢到爆
输入描述:
第一行两个整数n和m,表示数列长度和询问次数
第二行有n个整数,表示这个数列的初始数值
接下来有m行,形如 1 l r 或者 2 l r k
分别表示查询∑i=lrai\sum_{i=l}^{r} a_i∑i=lrai
或者对于l ≤ i ≤ r,将xi变为xi⊕kx_i \oplus kxi⊕k
输出描述:
对于每一个查询操作,输出查询的结果并换行
示例1
备注:
1. 数据范围
对于30%30\%30%的数据,保证 n, m, k≤ 10
对于另外30%30\%30%的数据,保证 n, m ≤ 50000, k ∈ {0, 1}
对于全部100%100\%100%的数据,保证 1 ≤ n,m ≤ 105, 0≤ ai,k ≤ 105
2. 说明
a⊕ba \oplus ba⊕b表示a xor ba \text{ xor } ba xor b
分析
异或和不能直接加,所以得按位挨个改,然后挨个加权值。
//-------------------------代码---------------------------- //#define int ll const int N = 1e5+10; int n,m,k; struct node { int l,r,lazy; int s[2]; } tr[21][N<<2]; int a[N]; #define root tr[id][u] #define lt tr[id][ul] #define rh tr[id][ur] void push_up(int id,int u) { tr[id][u].s[0] = tr[id][ul].s[0] + tr[id][ur].s[0]; tr[id][u].s[1] = tr[id][ul].s[1] + tr[id][ur].s[1]; } void change(int id,int u) { swap(tr[id][u].s[0],tr[id][u].s[1]); tr[id][u].lazy ^= 1; } void push_down(int id,int u) { if(tr[id][u].lazy) { tr[id][u].lazy = 0; change(id,ul);change(id,ur); } } void build(int id,int u,int l,int r) { tr[id][u] = {l,r,0}; if(l == r) { tr[id][u].s[(a[l]>>id) & 1] =1; tr[id][u].s[0] = (a[l] & (1<<id)) == 1?0 :1; rt; } int mid = l + r >> 1; build(id,ul,l,mid);build(id,ur,mid+1,r); push_up(id,u); } void modify(int id,int u,int l,int r) { if(l <= root.l && root.r <= r) { change(id,u);rt; } push_down(id,u);int mid = root.l + root.r >> 1; if(l <= mid) modify(id,ul,l,r); if(mid < r) modify(id,ur,l,r); push_up(id,u); } int query(int id,int u,int l,int r) { if(l <= root.l && root.r <= r) { return root.s[1]; } if(l > root.r || root.l > r) return 0; push_down(id,u); return query(id,ul,l,r) + query(id,ur,l,r); } void solve() { // cin>>n>>m; cin>>n>>k; fo(i,1,n) cin>>a[i]; fo(i,0,20) { build(i,1,1,n); } while(k--) { int op,l,r,x;cin>>op>>l>>r; if(op == 1) { ll ans = 0; fo(i,0,20) { ans += 1ll * query(i,1,l,r) * (1<<i); } cout<<ans<<endl; } else { cin>>x; fo(i,0,20) { if((x >> i) & 1) modify(i,1,l,r); } } } } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------