codeforces 242E - XOR on Segment (线段树 按位数建树)
4 seconds
256 megabytes
standard input
standard output
You've got an array a, consisting of n integers a1, a2, ..., an. You are allowed to perform two operations on this array:
- Calculate the sum of current array elements on the segment [l, r], that is, count value al + al + 1 + ... + ar.
- Apply the xor operation with a given number x to each array element on the segment [l, r], that is, execute . This operation changes exactly r - l + 1 array elements.
Expression means applying bitwise xor operation to numbers x and y. The given operation exists in all modern programming languages, for example in language C++ and Java it is marked as "^", in Pascal — as "xor".
You've got a list of m operations of the indicated type. Your task is to perform all given operations, for each sum query you should print the result you get.
The first line contains integer n (1 ≤ n ≤ 105) — the size of the array. The second line contains space-separated integers a1, a2, ..., an(0 ≤ ai ≤ 106) — the original array.
The third line contains integer m (1 ≤ m ≤ 5·104) — the number of operations with the array. The i-th of the following m lines first contains an integer ti (1 ≤ ti ≤ 2) — the type of the i-th query. If ti = 1, then this is the query of the sum, if ti = 2, then this is the query to change array elements. If the i-th operation is of type 1, then next follow two integers li, ri (1 ≤ li ≤ ri ≤ n). If the i-th operation is of type 2, then next follow three integers li, ri, xi (1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 106). The numbers on the lines are separated by single spaces.
For each query of type 1 print in a single line the sum of numbers on the given segment. Print the answers to the queries in the order in which the queries go in the input.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams, or the %I64dspecifier.
5
4 10 3 13 7
8
1 2 4
2 1 3 3
1 2 4
1 3 3
2 2 5 5
1 1 5
2 1 2 10
1 2 3
26
22
0
34
11
6
4 7 4 0 7 3
5
2 2 3 8
1 1 5
2 3 5 1
2 4 5 6
1 2 3
38
28
题意;
两个操作:
1.输出区间l,r的和
2.让区间l,r每个数异或x
思路:
把数拆成二进制,对每一位建一棵线段树,记录每个数这一位是否为1,然后求一段区间的和就是这些线段树上这一段区间1的个数乘上2的位数-1次方,异或一个数x的话,我们将x拆成二进制,如果x的某一位为1的话那么就是对这段区间所有数的这一位都要变化,这一位线段树上直接区间异或标记就好了。
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long
const int M = 1e5 + ; int sum[M<<][],lazy[M<<][],a[M],bit[]; void pushup(int rt){
for(int i = ;i <= ;i ++)
sum[rt][i] = sum[rt<<][i] + sum[rt<<|][i];
} void pushdown(int l,int r,int rt){
for(int i = ;i <= ;i ++)
if(lazy[rt][i]){
mid;
sum[rt<<][i] = m-l+-sum[rt<<][i];
sum[rt<<|][i] = r-m-sum[rt<<|][i];
lazy[rt<<][i] ^= lazy[rt][i];
lazy[rt<<|][i] ^= lazy[rt][i];
lazy[rt][i] = ;
}
} void build(int l,int r,int rt){
if(l == r){
int x = a[l],cnt = ;
while(x){
sum[rt][cnt++] = x%;
x = x/;
}
return;
}
mid;
build(lson); build(rson);
pushup(rt);
} void update(int L,int R,int x,int l,int r,int rt){
if(L <= l&&R >= r){
for(int i = ;i <= ;i ++){
if(x&(<<(i-))){
sum[rt][i] = r-l+-sum[rt][i];
lazy[rt][i] ^= ;
}
}
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update(L,R,x,lson);
if(R > m) update(L,R,x,rson);
pushup(rt);
} ll query(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
ll cnt = ;
for(int i = ;i <= ;i ++){
cnt += 1LL*sum[rt][i]*bit[i];
}
return cnt;
}
pushdown(l,r,rt);
mid; ll ret = ;
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
} int main(){
int n,q,l,r,x,op;
bit[] = ;
for(int i = ;i <= ;i ++)
bit[i] = bit[i-]*;
while(scanf("%d",&n)!=EOF){
for(int i = ;i <= n;i ++)
scanf("%d",&a[i]);
build(,n,);
scanf("%d",&q);
while(q--){
scanf("%d",&op);
if(op == ){
scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r,,n,));
}
else{
scanf("%d%d%d",&l,&r,&x);
update(l,r,x,,n,);
}
}
}
return ;
}
codeforces 242E - XOR on Segment (线段树 按位数建树)的更多相关文章
- codeforces 242E. XOR on Segment 线段树
题目链接 给n个数, 两种操作, 一种是求区间内的数的和, 一种是将区间内的数异或x. 异或x没有什么思路, 单个异或肯定超时, 区间异或也没有办法做....后来才知道可以按位建线段树, 这样建20棵 ...
- codeforces 22E XOR on Segment 线段树
题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...
- CodeForces 242E - XOR on Segment 二维线段树?
今天练习赛的题....又是线段树的变换..拿到题我就敲了个点更新区间查询的..果断超时...然后想到了可以将每个数与合表示成不进位的二进制数..这样就可以区间进行更新了..比赛的时候写搓了..刚重写了 ...
- CodeForces 242E "XOR on Segment"(线段树)
传送门 •题意 给你一个包含 n 个数的序列 a,定义序列上的两个操作: (1)$1,l,r\ :\ ans=\sum_{i=l}^{r}a_i$; (2)$2,l,r,x\ :\ \forall\ ...
- Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)
题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题 ...
- XOR on segment(线段树区间异或更新)
原题传送门 本题大意:给定n个数字和m个操作,操作共有两种,第一种是求解区间l到r上元素的和,第二种是将区间l到r的元素都异或一个x,作为某个位置的新值. 很容易想到线段树维护区间和,但是我们发现,在 ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- luogu P2574 XOR的艺术 (线段树)
luogu P2574 XOR的艺术 (线段树) 算是比较简单的线段树. 当区间修改时.\(1 xor 1 = 0,0 xor 1 = 1\)所以就是区间元素个数减去以前的\(1\)的个数就是现在\( ...
- CodeForces 516C Drazil and Park 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/8990745.html 题目传送门 - CodeForces 516C 题意 在一个环上,有$n$棵树. 给出每一 ...
随机推荐
- Python_每日习题_0007_copy
题目:将一个列表的数据复制到另一个列表中. 程序分析:使用列表[:],拿不准可以调用copy模块 import copy a = [,,,,['a','b']] b = a #赋值 c = a[:] ...
- Python_每日习题_0003_完全平方数
# 题目 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? # 程序分析 因为168对于指数爆炸来说实在太小了,所以可以直接省略数学分析,用最朴素的方法来获取 ...
- c++入门之再次探讨类属性
精辟博文:https://blog.csdn.net/msdnwolaile/article/details/51923859(转载,仅供学习|!)
- numpy中random的使用
import numpy as np a=np.random.random()#用于生成一个0到1的随机浮点数: 0 <= n < 1.0print(a)0.772000903322952 ...
- JVM原理分析
1 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.由一套字节码指令集.一组寄存器.一个栈.一个垃圾回收 ...
- js this的含义以及讲解
this关键字是一个非常重要的语法点.毫不夸张地说,不理解它的含义,大部分开发任务都无法完成. 首先,this总是返回一个对象,简单说,就是返回属性或方法“当前”所在的对象. 下面来两个例子来让大家更 ...
- centos6.5安装配置NTP,集群各机器间时间同步
试验环境 提君博客原创 >>提君博客原创 http://www.cnblogs.com/tijun/ << IP 主机名 角色 描述 同步方式 192.168.11.11 ...
- 第四周作业&&结对编程
1. 结对编程. 本周开始,和我结对编程的小伙伴是齐嘉亮(博客:http://www.cnblogs.com/zhengrui0452/). 因为这周需要发布四人团队项目的alpha版本,刚好我和亮哥 ...
- Java多线程3:Thread中的实例方法
一.Thread类中的方法调用方式 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: ...
- No module named 'ConfigParser'
系统: CentOS-6.4-x86_64 Python : Python 3.4.5 和 Python 3.5.2 安装 MySQL-python ,结果出错: ImportError: No mo ...