题意:
给一个具有n个数字的序列,并且有要进行m个操作
操作有两种:
1.修改序列中一个数字的值
2.给定一个区间[l,r],给出f(l,l)^f(l,l+1)...f(l,r)^...f(l+1,l+1)^...f(l+1,r)^....^f(r,r)
其中f(l,r)=al^a(l+1)^...a(r)
思路:第一种情况就是一个单点操作,然后第二种情况,很容易发现规律,对于r-l+1为偶数,就输出0,如果是奇数,就是f(l,l)^f(l,l+2)...f(l,r-1)。
#include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<stdlib.h> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1e5+7; int ans[maxn*4]; int tmp[maxn*4]; int a[maxn]; void pushup(int p){ ans[p]=ans[p<<1]^ans[p<<1|1]; tmp[p]=tmp[p<<1]^tmp[p<<1|1]; } void build(int l,int r,int p){ if(l==r){ if(l%2==1) ans[p]=a[l]; else tmp[p]=a[l]; return ; } int m=(l+r)>>1; build(l,m,p<<1); build(m+1,r,p<<1|1); pushup(p); } int query(int l,int r,int L,int R,int p){ if(L<=l&&r<=R){ if(L%2==1) return ans[p]; else return tmp[p]; } int m=(l+r)>>1; int kk=0; if(L<=m) kk=kk^query(l,m,L,R,p<<1); if(R>m) kk=kk^query(m+1,r,L,R,p<<1|1); return kk; } void update(int l,int r,int i,int j,int p){ if(l==r){ if(i%2==1) ans[p]=j; else tmp[p]=j; return ; } int m=(l+r)>>1; if(i<=m) update(l,m,i,j,p<<1); else update(m+1,r,i,j,p<<1|1); pushup(p); } int main(){ int t; scanf("%d",&t); int kase=1; while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); printf("Case #%d: ",kase++); while(m--){ int x,l,r; scanf("%d%d%d",&x,&l,&r); if(x==1){ int ans=0; if((r-l+1)%2==1){ ans=query(1,n,l,r,1); printf("%d ",ans); }else printf("0 "); }else{ update(1,n,l,r,1); } } } return 0; }