Untitled

mail@pastecode.io avatar
unknown
c_cpp
5 months ago
4.4 kB
3
Indexable
#include <bits/stdc++.h>

using namespace std;

#define ll long long

void FIO() {
#ifndef ONLINE_JUDGE
    freopen("../in.txt", "r", stdin);
    freopen("../out.txt", "w", stdout);
#endif
}

const int MAX_BIT = 20;

struct basis {
    vector<int> b;
    int n;

    void insert(int x) {
        for (int i: b) {
            x = min(x, i ^ x);
        }
        if (x) {
            ++n;
            b.push_back(x);
            for (int i = n - 1; i > 0; --i) {
                if (b[i] > b[i - 1]) {
                    swap(b[i], b[i - 1]);
                }
            }
        }
    }

    void join(const basis &other) {
        if (n == MAX_BIT) return;
        for (int i: other.b) {
            insert(i);
        }
    }

    int get_mx() {
        int res = 0;
        // sorted in decreasing order
        for (int i: b) {
            res = max(res, res ^ i);
        }
        return res;
    }

    basis() : n(0) {}
};


basis merge(const basis &a, const basis &b) {
    basis res = a;
    res.join(b);
    return res;
}

struct item {
    int x;
    basis b;

    void insert(int y) {
        b.insert(y);
    }

    void clear() {
        b = basis();
    }

    item() : x(-1) {}
};

struct segTree {
    vector<item> tree;
    int size;

    void init(int n) {
        size = 1;
        while (size < n) size *= 2;
        tree.assign(2 * size, item());
    }

    void propagate(int x, int lx, int rx) {
        if (tree[x].x == -1) return;
        if (rx - lx != 1) {
            tree[2 * x + 1].x &= tree[x].x;
            tree[2 * x + 2].x &= tree[x].x;
        }

        basis b = tree[x].b;
        tree[x].clear();
        for (int i: b.b) {
            tree[x].insert(i & tree[x].x);
        }
        tree[x].x = -1;
    }

    void build(vector<int> &a, int x, int lx, int rx) {
        if (rx - lx == 1) {
            if (lx < a.size()) {
                tree[x].insert(a[lx]);
            }
            return;
        }
        int m = (lx + rx) / 2;
        build(a, 2 * x + 1, lx, m);
        build(a, 2 * x + 2, m, rx);
        tree[x].b = merge(tree[2 * x + 1].b, tree[2 * x + 2].b);
    }

    void build(vector<int> &a) {
        init(a.size());
        build(a, 0, 0, size);
    }

    void update(int l, int r, int v, int x, int lx, int rx) {
        propagate(x, lx, rx);
        if (lx >= r || rx <= l) return;
        if (lx >= l && rx <= r) {
            tree[x].x = v;
            propagate(x, lx, rx);
            return;
        }

        int m = (lx + rx) / 2;
        update(l, r, v, 2 * x + 1, lx, m);
        update(l, r, v, 2 * x + 2, m, rx);
        tree[x].b = merge(tree[2 * x + 1].b, tree[2 * x + 2].b);
    }

    void update(int l, int r, int v) {
        update(l, r, v, 0, 0, size);
    }

    void set(int i, int v, int x, int lx, int rx) {
        propagate(x, lx, rx);
        if (lx > i || rx <= i) return;
        if (rx - lx == 1) {
            tree[x].clear();
            tree[x].insert(v);
            return;
        }
        int m = (lx + rx) / 2;
        set(i, v, 2 * x + 1, lx, m);
        set(i, v, 2 * x + 2, m, rx);
        tree[x].b = merge(tree[2 * x + 1].b, tree[2 * x + 2].b);
    }

    void set(int i, int v) {
        set(i, v, 0, 0, size);
    }

    basis query(int l, int r, int x, int lx, int rx) {
        propagate(x, lx, rx);
        if (lx >= r || rx <= l) return basis();
        if (lx >= l && rx <= r) return tree[x].b;
        int m = (lx + rx) / 2;
        basis s1 = query(l, r, 2 * x + 1, lx, m);
        basis s2 = query(l, r, 2 * x + 2, m, rx);
        return merge(s1, s2);
    }

    basis query(int l, int r) {
        return query(l, r, 0, 0, size);
    }
};


void solve() {
    int n, q;
    cin >> n >> q;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    segTree st;
    st.build(a);
    while (q--) {
        int t;
        cin >> t;
        if (t == 1) {
            int l, r, v;
            cin >> l >> r >> v;
            st.update(l - 1, r, v);
        } else if (t == 2) {
            int i, v;
            cin >> i >> v;
            st.set(i - 1, v);
        } else {
            int l, r;
            cin >> l >> r;
            cout << st.query(l - 1, r).get_mx() << '\n';
        }
    }
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    FIO();

    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
Leave a Comment