Many Operations(位运算、递推)

题意

给定一个变量\(X\)\(N\)个操作,每个操作用\((T_i, A_i)\)来表示。

  • 如果\(T_i = 1\),则将\(X\)替换为\(X \& A_i\)
  • 如果\(T_i = 2\),则将\(X\)替换为\(X | A_i\)
  • 如果\(T_i = 3\),则将\(X\)替换为\(X xor A_i\)

\(X\)初始化为\(C\),然后按照次序执行如下操作:

实施第\(1\)个操作,然后输出结果\(X\)
实施第\(1,2\)个操作,然后输出结果\(X\)
实施第\(1,2,3\)个操作,然后输出结果\(X\)
......
实施第\(1,2,\dots , N\)个操作,然后输出结果\(X\)

题目链接:https://atcoder.jp/contests/abc261/tasks/abc261_e

数据范围

\(1 \leq N \leq 2 \times 10^5\)
\(0 \leq C,A_i < 2^{30}\)

思路

这种题一般是进行递推。

一开始我想的是,递推\(A_1,A_2,\dots, A_i\),但是发现这个结论是错误的。

正确做法是对每一位分别进行考虑,并且分别假设每一位是\(0\)\(1\),进行递推。

(有点难表达,直接看代码吧)

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 200010;

int n, c;
int op[N], x[N];
int f[35][2];

int main()
{
    scanf("%d%d", &n, &c);
    for(int i = 1; i <= n; i ++) scanf("%d%d", &op[i], &x[i]);
    for(int i = 0; i < 30; i ++) f[i][1] = 1;
    for(int i = 1; i <= n; i ++) {
        for(int j = 0; j < 30; j ++) {
            int t = x[i] >> j & 1;
            if(op[i] == 1) {
                f[j][0] &= t;
                f[j][1] &= t;
            }
            else if(op[i] == 2) {
                f[j][0] |= t;
                f[j][1] |= t;
            }
            else {
                f[j][0] ^= t;
                f[j][1] ^= t;
            }
        }
        int p = 0;
        for(int j = 29; j >= 0; j --) {
            int t = c >> j & 1;
            p = p * 2 + f[j][t];
        }
        c = p;
        printf("%d\n", c);
    }
    return 0;
}
posted @ 2022-09-13 22:02  pbc的成长之路  阅读(14)  评论(0编辑  收藏  举报