2019南昌邀请赛-F

F - Sequence

Oldjang has a sequence A of length n , the i t h number in which is A i . He defined a function f ( l , r ) = a l ⊕ a l + 1 ⊕ ⋯ ⊕ a r . It is simple for the cleverest boy oldjang to calculate the function, so he wants to make the problem more difficult for fun. He will perform two operations: The operation expressed as " 0 x y ", which means he changes the x t h number to y ; The operation expressed as " 1 l r ", which means he wants to calculate the function F ( l , r ) . F ( l , r ) = f ( l , l ) ⊕ f ( l , l + 1 ) ⊕ ⋯ ⊕ f ( l , r ) ⊕ f ( l + 1 , l + 1 ) ⊕ ⋯ f ( l + 1 , r ) ⊕ ⋯ ⊕ f ( r , r ) . That means F ( l , r ) equals to the x or sum of all f ( i , j ) satisfied l ≤ i ≤ j ≤ r . Oldjang thinks the problem is still too simple for him, so he gives this task to you.
Input
The first line contains a integers T ( 1 ≤ T ≤ 10 ) — the number of test cases . The second line contains two integers n , m ( 1 ≤ n , m ≤ 10 5 ) , which means the sequence has n numbers and oldjang has m operations. The next line contains n integers — the sequence A . In the following m lines, each line contains three integers " 0 x y " or " 1 l r " ,descriping a operation. Output
For each test case, print one line containing "Case # x : " first, where x is the test case number (starting from 1 ). Then output the answer after each the operations of second type.
Sample Input

1 
3 3 
1 2 3
1 1 3 
0 1 2
1 1 1 

Sample Output

Case #1:
2
2

题意:给定数组,按照题中的公式,求出结果,另外还要对数组进行修改。

将题中的公式化简,就会发现规律,所求区间长度为偶数时,结果为零,奇数时,从左边界开始,隔项异或,输出结果。结合要进行数据修改,所以选择了线段树进行维护,将输入的数组分了两组,一组奇数,一组偶数,分别维护两数组的线段树即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+500;
struct Tree{
	int val0,val1,l,r;
}t[N*4];
int a0[N],a1[N];
void undata(int p){
	t[p].val0=t[p*2].val0^t[p*2+1].val0;
	t[p].val1=t[p*2].val1^t[p*2+1].val1;
}
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r;
	if(l==r){
		t[p].val0=a0[l];
		t[p].val1=a1[l];
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	undata(p);
}
void change0(int p,int x,int val){
	if(t[p].l==t[p].r){
		t[p].val0=val;
		return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(x<=mid){
		change0(p*2,x,val);
	}else{
		change0(p*2+1,x,val);
	}
	undata(p);
}
void change1(int p,int x,int val){
	if(t[p].l==t[p].r){
		t[p].val1=val;
		return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(x<=mid){
		change1(p*2,x,val);
	}else{
		change1(p*2+1,x,val);
	}
	undata(p);
}
int ask0(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r){
		return t[p].val0;
	}
	int mid=(t[p].l+t[p].r)/2;
	int ans=0;
	if(l<=mid){
		ans=ans^ask0(p*2,l,r);
	}
	if(r>mid){
		ans=ans^ask0(p*2+1,l,r);
	}
	return ans;
}
int ask1(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r){
		return t[p].val1;
	}
	int mid=(t[p].l+t[p].r)/2;
	int ans=0;
	if(l<=mid){
		ans=ans^ask1(p*2,l,r);
	}
	if(r>mid){
		ans=ans^ask1(p*2+1,l,r);
	}
	return ans;
}
int main(){
	int T;
	scanf("%d",&T);
	for(int k=1;k<=T;++k){
		int n,m;
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;++i){
			int x;
			scanf("%d",&x);
			if(i%2){
				a1[i]=x;
				a0[i]=0;
			}else{
				a1[i]=0;
				a0[i]=x;
			}
		}
		build(1,1,n);
		printf("Case #%d:\n",k);
		while(m--){
			int z,x,y;
			scanf("%d %d %d",&z,&x,&y);
			if(z==0){
				if(x%2){
					change1(1,x,y);
				}else{
					change0(1,x,y);
				}
			}else{
				if((y-x)%2){
					printf("0\n");
				}else{
					if(x%2){
						printf("%d\n",ask1(1,x,y));
					}else{
						printf("%d\n",ask0(1,x,y));
					}
				}
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值