Loading

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;
}
posted @ 2023-05-17 15:30  chengning0909  阅读(4)  评论(0编辑  收藏  举报