【洛谷P6225】异或橙子

期中刚考完就过来接着学算法啦

毕竟oop那堆东西基本上放到开发工程效率提高才比较明显,放到这里其实就不大行了
那么,我们今天还是看一道树状数组的题目,明天开始学习线段树
奇怪。这些东西当年我不是都会吗

P6225 [eJOI 2019] 异或橙子

题目描述

Janez 喜欢橙子!他制造了一个橙子扫描仪,但是这个扫描仪对于扫描的每个橙子的图像只能输出一个 \(32\) 位整数。

他一共扫描了 \(n\) 个橙子,但有时他也会重新扫描一个橙子,导致这个橙子的 \(32\) 位整数发生更新。

Janez 想要分析这些橙子,他觉得异或操作非常有趣,他每次选取一个区间从 \(l\)\(u\),他想要得到这个区间内所有子区间的异或和的异或和。

例如 \(l=2,u=4\) 的情况,记橙子序列 \(A\) 中第 \(i\) 个橙子的整数是 \(a_i\),那么他要求的就是:

\[a_2 \oplus a_3 \oplus a_4 \oplus (a_2\oplus a_3)\oplus(a_3\oplus a_4)\oplus(a_2\oplus a_3 \oplus a_4) \]


注:式子中的 \(\oplus\) 代表按位异或运算。异或的运算规则如下。

对于两个数的第 \(i\) 位,记为 \(x,y\),那么:

\(x\) \(y\) \(x\oplus y\)
\(0\) \(1\) \(1\)
\(1\) \(0\) \(1\)
\(0\) \(0\) \(0\)
\(1\) \(1\) \(0\)

例:\(13\oplus 23=26\)

\(13=\) \(0\cdots 001101\)
\(23=\) \(0\cdots 010111\)
\(13\oplus 23=\) \(0\cdots 011010\)

输入格式

第一行输入两个正整数 \(n,q\),表示橙子数量和操作次数。

接下来一行 \(n\) 个非负整数,表示每个橙子扫描得到的数值 ,从 \(1\) 开始编号。

接下来 \(q\) 行,每行三个数:

  • 如果第一个数是 \(1\),接下来输入一个正整数 \(i\) 与非负整数 \(j\),表示将第 \(i\) 个橙子的扫描值 \(a_i\) 修改为 \(j\)

  • 如果第一个数是 \(2\),接下来输入两个正整数 \(u,l\) 表示询问这个区间的答案。

输出格式

对于每组询问,输出一行一个非负整数,表示所求的总异或和。

输入输出样例 #1

输入 #1

3 3
1 2 3
2 1 3
1 1 3
2 1 3

输出 #1

2
0

输入输出样例 #2

输入 #2

5 6
1 2 3 4 5
2 1 3
1 1 3
2 1 5
2 4 4
1 1 1
2 4 4

输出 #2

2
5
4
4

说明/提示

输入输出样例 1 解释

  • 最初,\(A=[1,2,3]\),询问结果为 \(1\oplus 2\oplus 3\oplus(1\oplus 2)\oplus (2\oplus 3)\oplus(1\oplus 2\oplus 3)=2\)

  • 修改后,第一个位置被修改为 \(3\) ,询问的结果是 \(3\oplus 2\oplus 3\oplus(3\oplus 2)\oplus (2\oplus 3)\oplus(3\oplus 2\oplus 3)=0\)


数据规模与约定:

本题采用多测试点捆绑测试,共有 5 个子任务

  • Subtask 1(12 points):\(1\le n,q\le 10^2\),无特殊限制
  • Subtask 2(18 points):\(1\le n,q\le 5\times 10^2\),且没有修改操作。
  • Subtask 3(25 points):\(1\le n,q\le 5\times 10^3\),无特殊限制
  • Subtask 4(20 points):\(1\le n,q\le 2\times 10^5\),且没有修改操作。
  • Subtask 5(25 points):\(1\le n,q\le 2\times 10^5\),无特殊限制

对于所有数据,\(0\le a_i\le 10^9,1\le n,q\le 2\times 10^5\)


说明

原题来自:eJOI2019 Problem A. XORanges

题面&数据来自:LibreOJ

解法&&个人感想

其实这道题我还是看了洛谷题解的
虽然数学原理自己推出来了,但是实现上出了问题
不过,这道题还是可以让我们学会很多关于异或的知识
首先,我们知道了异或是符合交换律和结合律的,所以任意的括号都可以打开
现在,我们考虑一个数列\(a_1,a_2\ldots a_m\),对其求任意子区间的异或和,我们可以计算出,对于\(a_i\),其在这个表达式中出现了\(i(m-i+1)\)次,由于异或的偶数变0性,我们可以推出,当\(m,i\)均为奇数的时候,原式可以计算
这个时候怎么办呢?我们可以维护奇数和偶数分别两个树状数组,然后对其求异或和,就可以
而且不必加一堆繁文缛节,还可能导致出错,因为原来的函数其实某种意义上说,对不必要的数异或,并没有什么影响(因为0异或任何数,还是它本身)。
有一个小细节,就是我们在update的时候,原数组也要跟着变,因为我们有的操作是依托原数组的数完成的,就比如当更新异或值的时候,如果连续更新两次同一下标的元素,但是原数组却没有变的话,就会出问题了
下面看代码:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x&(-x))
#define maxn 200005
using namespace std;
int ma[maxn];
int n,q;
int op,a,b;
int oddtree[maxn];//奇数
int eventree[maxn];//偶数
void update_1(int a,int b){
    for(;a<=n;a+=lowbit(a)) eventree[a]^=b;
    return ;
}
void update_2(int a,int b){
    for(;a<=n;a+=lowbit(a)) oddtree[a]^=b;
    return ;
}
int query_1(int x){
    int ans=0;
    for(;x;x-=lowbit(x)) ans^=eventree[x];
    return ans;  
}
int query_2(int x){
    int ans=0;
    for(;x;x-=lowbit(x)) ans^=oddtree[x];
    return ans;
}
int main(){
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        cin>>ma[i];
        if(i%2) update_2(i,ma[i]);
        else update_1(i,ma[i]);
    }
    for(int i=1;i<=q;i++){
        cin>>op;
        if(op==1){
            cin>>a>>b;
            if(a%2==0){
                update_1(a,ma[a]^b);
                ma[a]=b;
            }
            else{
                update_2(a,ma[a]^b);
                ma[a]=b;
            }
        }
        else{
            cin>>a>>b;
            if((b-a)%2==1){
                cout<<0<<endl;
                continue;
            }
            else{
                if(a%2==0){
                    int ans_2=query_1(b);
                    int ans_1=query_1(a-1);
                    int temp=ans_2^ans_1;
                    cout<<temp<<endl;
                }
                else{
                    int ans_2=query_2(b);
                    int ans_1=query_2(a-1);
                    int temp=ans_2^ans_1;
                    cout<<temp<<endl;
                }
            }
        }
    }
    system("pause");
    return 0;
}

最近换壁纸啦!Charlotte的ED几张静态图真的绝美,还是8K的,用PS提一下亮度之后手上的Wallpaper Engine 顿时就不香了
后半学期,也请各位继续关注:
《我的青春线代物语果然有问题》
《高数女主养成计划》
《程设の旅》
《青春猪头少年不会梦到多智能体吃豆人》
《某Linux的开源软件》
新增:《Charlotte太空探索》(最符合学科内容的一集,Charlotte彗星怎么不是一种太空探索呢)
还有——

《我的算法竞赛不可能这么可爱》

本期到此结束!

posted @ 2025-05-14 23:37  elainafan  阅读(18)  评论(0)    收藏  举报