codeforces 22E XOR on Segment 线段树

题目链接:

http://codeforces.com/problemset/problem/242/E

E. XOR on Segment

time limit per test 4 seconds
memory limit per test 256 megabytes
#### 问题描述 > 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 %I64d specifier. #### 样例 > **sample input** > 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 > > **sample output** > 26 > 22 > 0 > 34 > 11 ## 题意 > 给你n个数,q个操作: > 查询:返回l到r的和 > 更新:l到r的每个数都异或上x。

题解

对没个数字按二进制展开,存放在20颗线段树里面。
然后就转化成了一个经典的区间更新区间查询的线段树问题了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#define lson (o<<1)
#define rson ((o<<1)|1)
#define M (l+(r-l)/2)
using namespace std;

const int maxn=1e5+10;
const int maxm=22;

typedef __int64 LL;

int n;

int sumv[maxm][maxn<<2];
int setv[maxn<<2];

void maintain(int o) {
	for(int i=0; i<maxm; i++) {
		sumv[i][o]=sumv[i][lson]+sumv[i][rson];
	}
}

void pushdown(int o,int l,int r) {
	for(int i=0; i<maxm; i++) {
		if(setv[o]&(1<<i)) {
			sumv[i][lson]=M-l+1-sumv[i][lson];
			sumv[i][rson]=r-M-sumv[i][rson];
		}
	}
	setv[lson]^=setv[o];
	setv[rson]^=setv[o];
	setv[o]=0;
}

void build(int o,int l,int r) {
	if(l==r) {
		int x;
		scanf("%d",&x);
		for(int i=0; i<maxm; i++) {
			if(x&(1<<i)) sumv[i][o]=1;
			else sumv[i][o]=0;
		}
	} else {
		build(lson,l,M);
		build(rson,M+1,r);
		maintain(o);
	}
}

int ql,qr,_v;
void update(int o,int l,int r) {
	if(ql<=l&&r<=qr) {
		for(int i=0; i<maxm; i++) {
			if(_v&(1<<i)) {
				sumv[i][o]=r-l+1-sumv[i][o];
			}
		}
		setv[o]^=_v;
	} else {
		pushdown(o,l,r);
		if(ql<=M) update(lson,l,M);
		if(qr>M) update(rson,M+1,r);
		maintain(o);
	}
}

LL _sum;
void query(int o,int l,int r){
	if(ql<=l&&r<=qr){
		for(int i=0;i<maxm;i++){
			_sum+=sumv[i][o]*((1LL)<<i);
		}
	}else{
		pushdown(o,l,r);
		if(ql<=M) query(lson,l,M);
		if(qr>M) query(rson,M+1,r);
		maintain(o);
	}
}

int main() {
	scanf("%d",&n);
	build(1,1,n);
	int q;
	scanf("%d",&q);
	while(q--) {
		int cmd;
		scanf("%d",&cmd);
		scanf("%d%d",&ql,&qr);
		if(cmd==1) {
			_sum=0;
			query(1,1,n);
			printf("%I64d\n",_sum);
		} else {
			scanf("%d",&_v);
			update(1,1,n);
		}
	}
	return 0;
}

Notes

其实和XOR有关的题目大部分都是套路!!!!二进制展开,你会发现一个新的世界!!!!

posted @ 2016-07-29 22:13  fenicnn  阅读(321)  评论(0编辑  收藏  举报