时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
在心理疏导室中有一种奇特的疏导工具,叫做红球。红球被提前分为了许多正方形小方格。
每当有人来找ATB做心理疏导时,ATB就会让他去先玩红球,然后通过红球小格方的高度来判断一个人的压力程度的高低
具体地讲,ATB会让该人对于一个序列执行以下操作
1. 区间求和,即输入l,r,输出
2. 区间异或,即输入l,r,k,对于l ≤ i ≤ r,将xi变为
可是ATB天天算计那么多答案,已经对这份工作产生了厌烦,所以请你帮帮他,对于一组给定的数据,输出对应的答案
ATB会将你感谢到爆
输入描述:
第一行两个整数n和m,表示数列长度和询问次数
第二行有n个整数,表示这个数列的初始数值
接下来有m行,形如 1 l r 或者 2 l r k
分别表示查询
或者对于l ≤ i ≤ r,将xi变为
输出描述:
对于每一个查询操作,输出查询的结果并换行
示例1
输入
复制
10 10
8 5 8 9 3 9 8 3 3 6
2 1 4 1
1 2 6
2 9 10 8
1 1 7
2 4 7 8
2 8 8 6
2 2 3 0
1 1 2
2 9 10 4
1 2 3
输出
复制
33
50
13
13
备注:
1. 数据范围
对于的数据,保证 n, m, k≤ 10
对于另外的数据,保证 n, m ≤ 50000, k ∈ {0, 1}
对于全部的数据,保证 1 ≤ n,m ≤ 105, 0≤ ai,k ≤ 105
2. 说明
表示
思路:
主要问题是处理Xor操作。可以用一个二维的线段树维护,第二维存储每一位中1的个数。然后区间更新。如果k的当前位为1,那么将tree[v][i]中的0变为1,1变为0,即1的个数为(R-L+1)-tree[v][i]。复杂度为O(nlogn*40)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define ll long long
int n,m;
ll tree[4*MAXN][40],laz[4*MAXN],que;
void build(int v,int L,int R)
{
if(L==R)
{
ll d;
scanf("%lld",&d);
for(int i=0;d;i++)
{
tree[v][i]=d&1;
d>>=1;
}
}
else
{
int mid=(L+R)/2;
build(v*2,L,mid);
build(v*2+1,mid+1,R);
for(int i=0; i<40; i++)
tree[v][i]=tree[v*2][i]+tree[v*2+1][i];
}
}
void pushdown(int L,int R,int v)
{
laz[v*2]^=laz[v];
laz[v*2+1]^=laz[v];
int d=laz[v];
int mid=(L+R)/2;
for(int i=0; i<20 && d; i++,d>>=1)
{
if(d&1)
{
tree[v*2][i]=(mid-L+1)-tree[v*2][i];
tree[v*2+1][i]=(R-mid)-tree[v*2+1][i];
}
}
laz[v]=0;
}
void updata(int v,int L,int R,int ql,int qr,ll q)
{
if(ql<=L && R<=qr)
{
ll d=q;
for(int i=0; i<20 && d; i++,d>>=1)
{
if(d&1) tree[v][i]=(R-L+1)-tree[v][i];
}
laz[v]^=q;
return;
}
if(laz[v]) pushdown(L,R,v);
int mid=(L+R)/2;
if(ql<=mid) updata(v*2,L,mid,ql,qr,q);
if(qr>mid) updata(v*2+1,mid+1,R,ql,qr,q);
for(int i=0; i<40; i++)
tree[v][i]=tree[v*2][i]+tree[v*2+1][i];
}
void query(int v,int L,int R,int ql,int qr)
{
if(ql<=L && R<=qr)
{
for(int i=0; i<40; i++)
que+=(1LL<<i)*tree[v][i];
return;
}
if(laz[v]) pushdown(L,R,v);
int mid=(L+R)/2;
if(ql<=mid) query(v*2,L,mid,ql,qr);
if(qr>mid) query(v*2+1,mid+1,R,ql,qr);
}
int main()
{
scanf("%d%d",&n,&m);
memset(tree,0,sizeof tree);
memset(laz,0,sizeof laz);
build(1,1,n);
for(int i=0; i<m; i++)
{
int op,l,r;
ll d;
scanf("%d",&op);
if(op==2)
{
scanf("%d%d%lld",&l,&r,&d);
updata(1,1,n,l,r,d);
}
else
{
scanf("%d%d",&l,&r);
que=0;
query(1,1,n,l,r);
printf("%lld\n",que);
}
}
return 0;
}