考虑异或差分 。操作 1 直接 即可。考虑操作 2 ,设 ,则对于 ,相当于对于区间 ,区间异或 后再依次异或上 ,第一部分与操作 1 同理,第二部分可以直接先打个标记,记为 ,执行完后 。重复上述操作直到 ,此时再从大到小枚举 执行上述操作直到填满区间 即可。处理完所有操作后考虑处理 ,从大到小枚举 ,实际上 相当于 ,相当于标记 ,然后区间 异或上 ,注意判断是否越界。

#include <bits/stdc++.h>
using namespace std;
const int N = 6e5 + 5;
int n, q, pw[20], s[N];
bitset<20> b[N];
inline void Solve() {
    int x, y = 0;
    for (int i = 1; i <= n; ++i)
        scanf("%d", &x), s[i] = x ^ y, y = x;
    for (int op, l, r; q--;) {
        scanf("%d%d%d%d", &op, &l, &r, &x);
        if (!op) {
            s[l] ^= x, s[r + 1] ^= x;
            continue;
        }
        for (int i = 0; i <= 19; ++i)
            if (x & pw[i] && l + pw[i] - 1 <= r)
                b[l][i].flip(), s[l] ^= x, s[l += pw[i]] ^= x, x += pw[i];
        for (int i = 19; i >= 0; --i)
            if (l + pw[i] - 1 <= r)
                b[l][i].flip(), s[l] ^= x, s[l += pw[i]] ^= x, x += pw[i];
    }
    for (int i = 1; i <= n; ++i)
        for (int j = 19; j >= 1; --j)
            if (b[i][j]) {
                b[i][j - 1].flip();
                if ((x = i + pw[j - 1]) > n)
                    continue;
                b[x][j - 1].flip(), s[x] ^= pw[j - 1];
                if (i + pw[j] <= n)
                    s[i + pw[j]] ^= pw[j - 1];
            }
    for (int i = 1; i <= n; ++i)
        printf("%d%c", s[i] ^= s[i - 1], " \n"[i == n]);
}
int main() {
    pw[0] = 1;
    for (int i = 1; i <= 19; ++i)
        pw[i] = pw[i - 1] << 1;
    while (~scanf("%d%d", &n, &q))
        Solve();
    return 0;
}