10 E. Data Structures Fan(异或性质、前缀和思想)
链接
题面
题解
异或的性质。
当异或遇到区间。
考虑用前缀和的思想解决。
这里分开处理0和1,因为最后我们要查询的是所有1和0位置处的
a
[
i
]
a[i]
a[i]的异或
我们考虑修改一段区间对于0、1的影响,我们希望将一段区间内的0处变成1,1变成0
然后假设我们现在这一段区间是
[
3
,
8
]
[3,8]
[3,8]
0:a[3] ^ a[5] ^ a[6]
1:a[4] ^ a[7] ^ a[8]
要使两者交换就需要异或上a[3] ^ a[4] ^ a[5] ^ a[6] ^ a[7] ^ a[8],也就是这个区间内所有数的异或
代码
#include <bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define vi vector<int>
using namespace std;
void solve() {
int n;
cin>>n;
vector<int>a(n+1);
vector<int>sum(n+1);
rep(i,1,n){
cin>>a[i];
sum[i]=sum[i-1]^a[i];
}
string s;
cin>>s;
vector<int>ans(2);
rep(i,0,s.size()-1){
if(s[i]=='0') ans[0]^=a[i+1];
else ans[1]^=a[i+1];
}
int q;
cin>>q;
while(q--){
int op;
cin>>op;
if(op==1){
int l,r;
cin>>l>>r;
ans[0]^=(sum[r]^sum[l-1]);
ans[1]^=(sum[r]^sum[l-1]);
}else{
int d;
cin>>d;
cout<<ans[d]<<' ';
}
}
cout<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("1.in", "r", stdin);
int _;
cin>>_;
while(_--)
solve();
return 0;
}
总结
- 所有逆运算的都可以通过前缀和思想来进行处理
- 加减
- 乘除
- 异或、异或