专栏文章
题解:P11872 异或盒子 1
P11872题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mipyxj2w
- 此快照首次捕获于
- 2025/12/03 20:13 3 个月前
- 此快照最后确认于
- 2025/12/03 20:13 3 个月前
比赛结束后几秒钟调出来的,提交失败,写个题解纪念一下。
考虑每次“加一”操作对每个二进制位的影响(代码中的 变量)。对每个数预处理出每个二进制位首次变化需要的“加一”次数并加入 中(代码中的 函数)后,该数第 位再次变化还需要的“加一”次数就恒为 了(代码中的 函数)。
在此基础上,可以动态维护 ,当需要改变一个数的时候,可以利用异或操作的幂等性,实现为在 中同时加入原来的数和新的数的贡献(代码中 函数里的两次 操作);当需要执行“加一”操作时,利用 中的信息直接更新答案即可。
时空复杂度 (空间复杂度可以压缩到线性),目前最优解。
C#include <array>
#include <iostream>
#include <vector>
#define endl '\n'
using namespace std;
int n, q;
vector<int> v;
vector<array<int, 20>> changes;
void add_num(int u, int o = 0)
{
for(int i = 0; i < 20; ++i) {
int j = o + (-u & ((1 << i) - 1));
if(j > q) break;
++changes[j][i]; // 自然溢出
}
}
void update_changes(int i)
{
for(int j = 0; j < 20; ++j) {
if(i - (1 << j) >= 0) changes[i][j] += changes[i - (1 << j)][j]; // 自然溢出
}
}
int main()
{
int ans = 0;
cin.tie(0)->sync_with_stdio(0);
cin >> n >> q;
v.resize(n);
changes.assign(q + 1, { 0 });
for(int &u : v) cin >> u, add_num(u), ans ^= u;
int s = 0;
for(int i = 0; i < q; ++i) {
int o, x, y;
cin >> o;
if(o == 0) {
cin >> x >> y, --x;
add_num(v[x] + s, s);
ans ^= v[x] + s;
v[x] = y - s;
ans ^= v[x] + s;
add_num(v[x] + s, s);
} else if(o == 1) {
update_changes(++s);
for(int j = 0; j < 20; ++j) ans ^= (changes[s][j] & 1) << j;
} else {
cout << ans << endl;
}
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...