赞
踩
1.对于区间异或 我们可以 仿照 前缀和的思路 对于前缀和 我们假设 原始数组为
a
[
N
]
a[N]
a[N] 那么前缀和 数组的公式可以写成
p
r
e
t
[
i
]
=
p
r
e
t
[
i
−
1
]
+
p
r
e
t
[
i
]
pret[i]=pret[i-1]+pret[i]
pret[i]=pret[i−1]+pret[i]
而对于比如 求解 区间 [l,r]的和 我们可以由以下的公式求解
a
n
s
=
p
r
e
t
[
j
]
−
p
r
e
t
[
i
−
1
]
;
ans=pret[j]-pret[i-1];
ans=pret[j]−pret[i−1];
对于异或运算 我们可以类比 一下前缀和的加法运算 用一个前缀和数组 来记录整个的 异或 和
但是 异或和 有一个问题 就是我们还原的时候应该怎么还原
对于这个问题 我们可以证明一下 请看以下的三个公式
a
⊕
b
=
c
两边同时异或上
b
等式仍然成立
a
⊕
b
⊕
b
=
c
⊕
b
异或满足结合律
a
⊕
(
b
⊕
b
)
=
c
⊕
b
a\oplus b=c \\ 两边同时异或上b 等式仍然成立 \\ a\oplus b\oplus b=c\oplus b \\ 异或满足结合律 a\oplus (b\oplus b )=c \oplus b
a⊕b=c两边同时异或上b等式仍然成立a⊕b⊕b=c⊕b异或满足结合律a⊕(b⊕b)=c⊕b
这样我们就可以得到一个很神奇的结论
a
⊕
b
=
c
a
=
b
⊕
c
其实异或运算最重要的性质就是自己和自己异或等于
0
以及异或满足结合律
我们做题的思路也是源于此
a \oplus b=c \quad a=b\oplus c \\ 其实异或运算最重要的性质就是自己和自己异或等于0 以及异或满足结合律\\ 我们做题 的思路也是源于此
a⊕b=ca=b⊕c其实异或运算最重要的性质就是自己和自己异或等于0以及异或满足结合律我们做题的思路也是源于此
那么我们的 前缀和 取一个
[
l
,
r
]
[l,r]
[l,r]的 区间 我们就可 采用以下的公式
然后 我们可以这么理解
p
r
e
t
[
r
]
=
a
1
⊕
a
2
⊕
a
3
⊕
⋯
⊕
a
r
p
r
e
t
[
l
−
1
]
=
a
1
⊕
a
2
⋯
⊕
a
l
−
1
我们要求解
a
l
⊕
a
l
+
1
…
a
r
那么我们的
p
r
e
t
[
l
−
1
]
⊕
p
r
e
t
[
r
]
那么就是
a
n
s
我们完全可以看作他们两个异或是
a
1
和
a
1
结合等于
0
这样以此类推最后得到结果
所以异或的前缀和完美解决
pret[r]=a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_r \\ pret[l-1]=a_1 \oplus a_2 \dots \oplus a_{l-1} \\ 我们要求解 a_l\oplus a_{l+1} \dots a_r \\ 那么 我们的 pret[l-1] \oplus pret[r] 那么就是 ans\\ 我们完全可以看作 他们两个异或 是a_1和a_1结合等于0 这样以此类推 最后得到 结果 \\所以 异或的 前缀和完美解决
pret[r]=a1⊕a2⊕a3⊕⋯⊕arpret[l−1]=a1⊕a2⋯⊕al−1我们要求解al⊕al+1…ar那么我们的pret[l−1]⊕pret[r]那么就是ans我们完全可以看作他们两个异或是a1和a1结合等于0这样以此类推最后得到结果所以异或的前缀和完美解决
https://codeforces.com/contest/1872/problem/E
//变量ans代表所有为1 的数异或的结果 对于为0的数异或的结果 我们可以 让ans和整个区间做异或 因为 这样为1的会自己和自己异或 //对于改变操作 我们只需要 让ans和这个区间再做一次异或 这样相同的异或就会消掉 不同的 就会得到计算 #include<iostream> #include<cstring> using namespace std; const int N=1e5+100; int a[N]; long long int pret[N]; string s; void solve() { int n; cin>>n; memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) { cin>>a[i]; } cin>>s; long long int ans=0; for(int i=1;i<=s.length();i++) { if(s[i-1]=='1'){ ans=ans^a[i]; } pret[i]=pret[i-1]^a[i]; } int q; cin>>q; while(q--) { int op; cin>>op; if(op==1){ int l,r; cin>>l>>r; ans=ans^(pret[r]^pret[l-1]); } else { int x; cin>>x; if(x==1) cout<<ans<<" "; else { int res=ans^pret[n]^pret[0]; cout<<res<<" "; } } } } int main() { int t; cin>>t; while(t--) { solve(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。