计蒜客40258 Sequence (区间异或/树状数组)

题目链接
在这里插入图片描述
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;         //不要忘记修改原数组的值
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值