洛谷 P6225 [eJOI 2019] 异或橙子 题解

题目链接

洛谷 P6225

题目大意

现有一个长度为 N N N 的数列 a a a,有 q q q 次操作,第一类操作为将 a i a_i ai 修改为 j j j,第二类操作为求 ⨁ i = l u ( ⨁ j = i u a j ) \bigoplus^u_{i=l}(\bigoplus^u_{j=i}{a_j}) i=lu(j=iuaj)

思路分析

由异或的性质可得 a ⊕ a = 0 a\oplus a=0 aa=0 a ⊕ 0 = a a\oplus0=a a0=a,同时异或拥有交换律和结合律,所以奇数个相同的数异或等于它本身,偶数个相同的数异或等于 0 0 0

另外,我们设 f l , r , x f_{l,r,x} fl,r,x ( l ≤ x ≤ r ) (l\le x\le r) (lxr) 表示区间 [ l , r ] [l,r] [l,r] 中包含 a x a_x ax 的子区间的个数。那么包含 a x a_x ax 的子区间必定可以表示为 a [ L , x ) a_{[L,x)} a[L,x) a x a_x ax a ( x , R ] a_{(x,R]} a(x,R] 三部分。第一部分有 C x − 1 − l + 1 1 + C x − 1 − l + 1 0 = x − l + 1 C^1_{x-1-l+1}+C^0_{x-1-l+1}=x-l+1 Cx1l+11+Cx1l+10=xl+1 种取法,第三部分有 C r − ( x + 1 ) + 1 1 + C r − ( x + 1 ) + 1 0 = r − x + 1 C^1_{r-(x+1)+1}+C^0_{r-(x+1)+1}=r-x+1 Cr(x+1)+11+Cr(x+1)+10=rx+1 种取法,根据乘法原理, f l , r , x = ( x − l ) × 1 × ( r − x ) = ( x − l + 1 ) ( r − x + 1 ) f_{l,r,x}=(x-l)\times1\times(r-x)=(x-l+1)(r-x+1) fl,r,x=(xl)×1×(rx)=(xl+1)(rx+1)

因为 ( x − l + 1 ) + ( r − x + 1 ) = r − l + 2 (x-l+1)+(r-x+1)=r-l+2 (xl+1)+(rx+1)=rl+2,所以当 r − l + 2 r-l+2 rl+2 为奇数,即 l , r l,r l,r 奇偶性不同时, x − l + 1 , r − x + 1 x-l+1,r-x+1 xl+1,rx+1 必有一个为奇数,即 x − l , r − x x-l,r-x xl,rx 中必有一个为偶数,所以 f l , r , x f_{l,r,x} fl,r,x 为偶数。当 r − l + 2 r-l+2 rl+2 为偶数,即 l , r l,r l,r 奇偶性相同时, x − l + 1 , r − x + 1 x-l+1,r-x+1 xl+1,rx+1 同奇偶。若两者同奇,即 l , r l,r l,r x x x 奇偶性相同,则 f l , r , x f_{l,r,x} fl,r,x 为奇数,反之则为偶数。

而答案要求的等同于 ⨁ i = l u ( a i ⊕ a i ⊕ ⋯ ⊕ a i ⏟ f l , u , i  个 ) \bigoplus^u_{i=l}{(\underbrace{a_i\oplus a_i\oplus\cdots\oplus a_i}_{f_{l,u,i}\ 个})} i=lu(fl,u,i  aiaiai),并且

a i ⊕ a i ⊕ ⋯ ⊕ a i ⏟ f l , u , i  个 = { a i , f l , u , i ≡ 1 ( m o d 2 ) 0 , f l , u , i ≡ 0 ( m o d 2 ) \underbrace{a_i\oplus a_i\oplus\cdots\oplus a_i}_{f_{l,u,i}\ 个}=\begin{cases} a_i&,f_{l,u,i}\equiv 1\pmod 2 \\ 0&,f_{l,u,i}\equiv 0\pmod 2 \end{cases} fl,u,i  aiaiai={ai0,fl,u,i1(mod2),fl,u,i0(mod2)

所以当 l , u l,u l,u 奇偶性不同时,答案就为 0 0 0。当 l , u l,u l,u 同奇偶时,若 l , u l,u l,u i i i 奇偶性相同,则 f l , u , i f_{l,u,i} fl,u,i 为奇数, a i a_i ai 对答案的贡献为 a i a_i ai;若 l , u l,u l,u i i i 奇偶性不同,则 f l , u , i f_{l,u,i} fl,u,i 为偶数, a i a_i ai 对答案的贡献为 0 0 0,即当 l , u l,u l,u 同奇偶时,答案为 a l ⊕ a l + 2 ⊕ ⋯ ⊕ a u a_l\oplus a_{l+2}\oplus\cdots\oplus a_u alal+2au

我们可以用线段树维护区间 [ l , r ] [l,r] [l,r] 中下标为奇数的元素的异或和与下标为偶数的元素的异或和。修改时只需将包含 a x a_x ax 的区间先异或原来的值,再异或修改后的值,其中两个原来 a x a_x ax 的值异或变为 0 0 0,对答案没有影响。

代码

#include<bits/stdc++.h>
using namespace std;

const int N=2e5+10;
int n,q,opt,x,y;
int a[N],odd[N*4],even[N*4];// odd[] 维护奇数的异或和,even[] 维护偶数的异或和

inline void push_up(int x){
    odd[x]=odd[x*2]^odd[x*2+1];
    even[x]=even[x*2]^even[x*2+1];
}
void build(int l,int r,int x){
    if (l==r){
        if (l%2==0) even[x]=a[l];
        else odd[x]=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,x*2);
    build(mid+1,r,x*2+1);
    push_up(x);
}
void update(int ux,int uc,int l,int r,int x){
    if (l==r){
        if (ux%2==0) even[x]=uc;
        else odd[x]=uc;
        return;
    }
    int mid=(l+r)/2;
    if (ux<=mid) update(ux,uc,l,mid,x*2);
    else update(ux,uc,mid+1,r,x*2+1);
    push_up(x);
}
int query(int ul,int ur,int l,int r,int x){
    if (ul<=l && ur>=r) return ul%2==0?even[x]:odd[x];
    int mid=(l+r)/2,ans=0; // 若 x 与 y 同为奇数则为 [l,r] 中下标为奇数的元素的异或和
    if (ul<=mid) ans^=query(ul,ur,l,mid,x*2);// 若 x 与 y 同为偶数则为 [l,r] 中下标为偶数的元素的异或和
    if (ur>=mid+1) ans^=query(ul,ur,mid+1,r,x*2+1);
    return ans;
}
int main(){
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;++i) scanf("%d",a+i);
    build(1,n,1);
    while (q--){
        scanf("%d%d%d",&opt,&x,&y);
        if (opt==1) update(x,y,1,n,1);
        else printf("%d\n",(x%2==y%2?query(x,y,1,n,1):0));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值