题目链接
emmm题目的需求大概就是,查询一段区间的异或和,或者单点修改一个地方。题面中的公式可以化简一下,变为奇偶异或。所以我们只需要用树状数组/线段树维护奇偶行的区间就行了。 这题树状数组写起来很方便,区间异或可以写成【1,R】^【1,L-1】 .注意每次单点修改以后要维持数组同步修改
int a[maxn];//奇数下标的树状数组
int b[maxn];//偶数下标的树状数组
int p[maxn];//原数组
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y,int arr[],int len) //x为树状数组下标 y为需要异或的数 arr为传入的数组 len为arr数组长度
{
while(x<=len)
{
arr[x]^=y;
x+=lowbit(x);
}
}
int qurey(int x,int arr[]) //查询x
{
int sum=0;
while(x)
{
sum^=arr[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int cas=0;
int T;
T=read();
while(T--)
{
mem(a,0);
mem(b,0);
cas++;
printf("Case #%d:\n",cas);
int n,m,la=0,lb=0;
n=read(),m=read();
int alen=(n+1)/2,blen=n-alen;
for(int i=1; i<=n; i++)
{
p[i]=read();
if(i%2)
{
add(++la,p[i],a,alen);
}
else
{
add(++lb,p[i],b,blen);
}
}
while(m--)
{
int op,x,y;
op=read(),x=read(),y=read();
if(op==1)
{
if((y-x+1)%2==0)
printf("0\n");
else
{
if(x%2)
{
int xx=(x+1)/2-1,yy=(y+1)/2;
int ans=qurey(yy,a)^qurey(xx,a);
printf("%d\n",ans);
}
else
{
int xx=x/2-1,yy=y/2;
int ans=qurey(yy,b)^qurey(xx,b);
printf("%d\n",ans);
}
}
}
else
{
if(x%2)
{
add((x+1)/2,y^p[x],a,alen);
}
else
{
add(x/2,y^p[x],b,blen);
}
p[x]=y; //不要忘记修改原数组的值
}
}
}
}