zoukankan      html  css  js  c++  java
  • 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
    ",_sum);
    		} else {
    			scanf("%d",&_v);
    			update(1,1,n);
    		}
    	}
    	return 0;
    }
    

    Notes

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

  • 相关阅读:
    Android application context/activity context与内存泄露(转)
    Android Slide Menu相关
    android 实现自定义卫星菜单
    关于引用Theme.AppCompat theme的报错问题
    java中volatile关键字的含义
    自定义控件其实很简单1/3
    Android 修改应用程序字体
    Android字体工作原理
    颜色渐变的算法
    Android系统下载管理DownloadManager功能介绍及使用示例
  • 原文地址:https://www.cnblogs.com/fenice/p/5719804.html
Copyright © 2011-2022 走看看