关于区间异或的线段树

题:https://codeforces.com/problemset/problem/242/E?csrf_token=e91633dfd98d038f51cc388731fe3f4d

题意:俩个操作,操作1:(l,r,x),区间[l,r]的数全部异或上x。操作2:(l ,r)输出区间[l,r]和;

分析:对数组a建线段树,对于线段树的每一个节点进行二进制拆位,每个位就统计有多少个1,更新操作对于涵盖区间的二进制位就等于其长度减去更新前的1的个数;

#include<bits/stdc++.h>
using namespace std;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int N=30;
const int M=1e5+5;
ll lz[M<<2][N],tr[M<<2][N],a[M];
void up(int root){
    for(int i=0;i<=20;i++)
        tr[root][i]=tr[root<<1][i]+tr[root<<1|1][i];
}
void build(int root,int l,int r){
    if(l==r){
        int x=a[l];
        for(int i=0;i<=20;i++){
            if(x&(1<<i)){
                tr[root][i]=1;
            }
        }
        return ;
    }
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
    up(root);
}
void pushdown(int root,int l,int r){
    for(int i=0;i<=20;i++){
        if(lz[root][i]){
           int midd=(l+r)>>1;
            tr[root<<1][i]=midd-l+1-tr[root<<1][i];
            tr[root<<1|1][i]=r-midd-tr[root<<1|1][i];
            lz[root<<1][i]^=lz[root][i];
            lz[root<<1|1][i]^=lz[root][i];
            lz[root][i]=0;
        }

    }
}
void update(int L,int R,int x,int root,int l,int r){
    if(L<=l&&r<=R){
        for(int i=0;i<=20;i++)
            if(x&(1<<i)){
                tr[root][i]=r-l+1-tr[root][i];///记录i位置二进制的个数
                lz[root][i]^=1;
            }
        return;

    }
    pushdown(root,l,r);
    int midd=(l+r)>>1;
    if(L<=midd)
        update(L,R,x,lson);
    if(R>midd)
        update(L,R,x,rson);
    up(root);
}
ll query(int L,int R,int root,int l,int r){
    if(L<=l&&r<=R){
        ll ans=0;
        for(int i=0;i<=20;i++){
            ans+=tr[root][i]*(1ll<<i);
        }
        return ans;
    }
    pushdown(root,l,r);
    int midd=(l+r)>>1;
    ll res=0;
    if(L<=midd)
        res=query(L,R,lson);
    if(R>midd)
        res+=query(L,R,rson);
    return res;
}
int main(){
    int n,m;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(1,1,n);
    scanf("%d",&m);
    while(m--){
        int op;
        scanf("%d",&op);
        if(op==1){
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(l,r,1,1,n));
        }
        else{
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            update(l,r,x,1,1,n);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/starve/p/12602350.html

时间: 2024-08-02 09:45:47

关于区间异或的线段树的相关文章

区间求最值 线段树

湖南师范大学 11460 区间求最值 区间求最值   Problem description   给定一个长度为N 的数组,有q个询问,每个询问是求在数组的一段区间内那个元素的因子的个数最大,比如24的因子的个数就是8.  Input   首先是一个整数t,表示有t组测试数据,每组测试数据的第一行是一个整数N(1<=N<=10^6),第二行有N个整数ai(1<=ai<=10^6,i=1,2,.....N)表示数组的元素.第三行有一个整数q(1<=q<=10^5),代表有

ZOJ2112 动态区间Kth(单点修改) 线段树+Treap写法

---恢复内容开始--- 题意:给出一个序列和操作次数, 每次操作修改一个位置的数 或者 询问一个区间第k小的数 分析:单点修改可以考虑线段树, 区间排名可以用平衡树 所以线段树+Treap 用一颗线段树将序列划分 每颗Treap中插入的是对应区间的数 在每个数加入时, 顺便将该数插入线段树中包含该位置的那些区间上的Treap即可 单点修改同理, 将所有包含要修改的位置的区间上的Treap都删去原数并插入新数 询问第k小的数:由于询问的区间不一定恰好对应某棵Treap, 不便直接求出名次, 但是

HDU 1754 - I Hate It &amp; UVA 12299 - RMQ with Shifts - [单点/区间修改、区间查询线段树]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师

敌兵布阵_区间求和问题_线段树 or 树状数组

敌兵布阵 TimeLimit: 2000/1000 MS (Java/Others)  MemoryLimit: 65536/32768 K (Java/Others) 64-bit integer IO format:%I64d Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所

区间的价值(线段树)百度之星

区间的价值 Accepts: 0 Submissions: 0 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在LLL,右端点在RRR,那么该区间的长度为(R−L+1)(R-L+1)(R−L+1). 现在聪明的杰西想要知道,对于长度为kkk的区间,最大价值的区间价值是多少.

!SPOJ 1043 多次查询区间最大连续和-线段树

题意:已知一个数列,现在有多次查询(a,b),查询区间[a,b]的最大连续和. 分析: 这道题没有更新操作,只有区间查询操作.动态在于待查询区间不同,最大连续和也不同.所以其实相当于每次查询的时候要计算一次待查询区间的最大连续和. 有3种情况: 1.待查询区间包含当前区间.那么就直接返回当前区间的最大连续和: 2.待查询区间在当前区间的左区间或右区间.那么在左或右区间递归查询即可: 3.待查询区间横跨当前区间的左右区间.那么:当前区间在左区间部分的最大连续和.在右区间部分的最大连续和.左右区间连

codedecision P1112 区间连续段 题解 线段树

题目描述:https://www.cnblogs.com/problems/p/P1112.html 题目链接:http://codedecision.com/problem/1112 线段树区间操作,每一个线段对应的点包含三个信息: \(l\):表示这个区间最左边的点的数值: \(r\):表示这个区间最右边的点的数值: \(cnt\):表示这个区间有多少个数值段. 合并的时候: 根节点的 \(l\) 值等于左儿子节点的 \(l\) 值: 根节点的 \(r\) 值等于右儿子节点的 \(r\) 值

I Hate It(区间最大问题,线段树)

很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input本题目包含多组测试,请处理到文件结束.在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目.学生ID编号分别从1编到N.第二行包含N个整数,代表这N个学生的初始成绩,其中第i

Counting Haybales 区间更新 多颗线段树

Counting Haybales Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 77  Solved: 31 [Submit][Status][Discuss] Description Farmer John is trying to hire contractors to help rearrange his farm, but so far all of them have quit when they saw the complicat