abc 261 e 题解
abc 261 e
题意
给定变量 \(X\),有 \(N\) 种操作,第 \(i\) 次操作用一个数对 \((T_i, A_i)\) 描述:
- \(T_i = 1, 2, 3\) 分别表示将 \(X\) 替换为 \(X \ and \ A_i, X \ or \ A_i\) 和 \(X \ xor \ A_i\)。
将 \(X\) 初始化为 \(C\),并做以下事情:
-
对 \(X\) 做操作 \(1\),并输出。
-
对 \(X\) 做操作 \(1, 2\),并输出。
-
\(\dots\)
-
对 \(X\) 做操作 \(1, 2, \dots, N\),并输出。
思路
如果我们每次都从头开始做,时间复杂度会达到 \(O(N ^ 2)\),会超时,那么我们应该怎么优化呢?
因为这里是位运算,所以我们可以考虑从每一位入手。
令 \(f_{0 / 1, i, j}\) 表示 \(X\) 的第 \(i\) 位为 \(0 / 1\),做到第 \(j\) 次操作时的答案。
那么,每次询问只要枚举当前的 \(X\) 的每一位,将答案合并起来即可。
代码
#include <iostream>
using namespace std;
const int N = 2e5 + 10;
int n, c, t[N], a[N], f[2][35][N], l;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> c;
for (int i = 1; i <= n; i++) {
cin >> t[i] >> a[i];
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 30; j++) {
f[i][j][0] = i;
for (int k = 1; k <= n; k++) {
int v = (a[k] >> j) & 1;
if (t[k] == 1) {
f[i][j][k] = f[i][j][k - 1] & v;
} else if (t[k] == 2) {
f[i][j][k] = f[i][j][k - 1] | v;
} else {
f[i][j][k] = f[i][j][k - 1] ^ v;
}
}
}
}
for (int i = 1; i <= n; i++) {
int ans = 0;
for (int j = 0, k = c; j < 30; j++, k >>= 1) {
ans += f[k & 1][j][i] * (1 << j);
}
cout << ans << '\n';
c = ans;
}
return 0;
}