专栏文章
七濑悠月
CF2115D题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mip3utcl
- 此快照首次捕获于
- 2025/12/03 05:43 3 个月前
- 此快照最后确认于
- 2025/12/03 05:43 3 个月前
赛后过的,但感觉难度 2900* 高了,为啥我场上不会做。
二选一异或有点复杂,我们不妨记 ,这样如果让答案一开始为所有 异或和,那么就是每次可以选择是否异或 ,使最终答案最大或最小。
我们经典地从高位往低位考虑,设 为所有 中最高位的位置,那么此时不论前面怎么决策,最后一个最高位为 的位置总能使得这一位变成决策者希望的最大或最小。形式化地,我们记下标集合 表示最高位为 的 的位置集合,记 ,那么如果 这个集合中最终操作得到答案的第 位和 的决策者想要的不同,那么 就会异或进入答案,否则不变。于是我们先判断当前答案的第 位是否需要 异或,然后把全部 中最高位是 的位置全部异或上 ,表示如果这一位选进答案,那么 是否选择的状态就要改变。容易发现这样操作一次最高位会降低,并且后面的操作不会改变更高的位置,所以最优。
时间复杂度 。
CPP#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
int n; LL A[N]; char S[N];
int main() {
freopen(".in", "r", stdin); freopen(".out", "w", stdout);
ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
int _; cin >> _;
while (_ --) {
cin >> n; LL Ans = 0, x;
for (int i = 1; i <= n; i ++) cin >> A[i], Ans ^= A[i];
for (int i = 1; i <= n; i ++) cin >> x, A[i] ^= x;
cin >> (S + 1);
for (int i = 59; i >= 0; i --) {
int t = n; while (t && !((A[t] >> i) & 1)) t --;
if (!t) continue;
if (((Ans >> i) & 1) ^ (S[t] == '1')) Ans ^= A[t];
for (int j = 1; j <= n; j ++) if ((A[j] >> i) & 1) A[j] ^= A[t];
} cout << Ans << "\n";
}
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...