洛谷 P6225 [eJOI2019]异或橙子 (树状数组)
-
题意:有\(n\)个数,起始值均为\(0\),进行\(q\)次操作,每次输入三个数,如果第一个数为\(1\),则将第\(i\)个数修改为\(j\),如果为\(2\),则求区间\([l,r]\)内的所有子区间的异或和.
-
题解:在纸上写一写画一画,能够发现规律,如果区间的左端点\(l\)和右端点\(r\)奇偶性不同,那么这个区间内的所以子区间的异或和一定为\(0\),如果相同,那么区间内的所有下标与端点的奇偶性不同的值均为\(0\),所以我们只要求区间内下标奇偶性和端点相同的异或和即可,为了方便我们可以直接开个大的结构体来记录奇数和偶数下标的情况,然后剩下的就是单纯的树状数组了.
-
代码:
int n,q; int a[N]; int op,x,y; int lowbit(int x){ return x&(-x); } struct BIT{ int c[N]; void update(int i,int k){ while(i<=n){ c[i]^=k; i+=lowbit(i); } } int get_sum(int i){ int res=0; while(i>0){ res^=c[i]; i-=lowbit(i); } return res; } }tree[2]; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n>>q; for(int i=1;i<=n;++i){ cin>>a[i]; tree[i&1].update(i,a[i]); } while(q--){ cin>>op>>x>>y; if(op==1){ tree[x&1].update(x,a[x]^y); //a[x]^a[x]^y=0^y=y; a[x]=y; } else{ if((x&1)!=(y&1)) cout<<0<<endl; else{ int ans=tree[x&1].get_sum(y)^tree[x&1].get_sum(x-1); cout<<ans<<endl; } } } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮