E. Duff as a Queen線段樹區間修改+線性基

傳送門

題意:給你一個數組,有兩種操作,一種區間xor一個值,一個是查詢區間xor的結果的種類數

對於一個給定的區間,我們可以通過求解線性基的方式求出結果的種類數,而現在只不過將其放在線段樹上維護區間線性基。

#include <bits/stdc++.h>

using namespace std;

struct L_B {
    long long d[31];

    void init() {
        memset(d, 0, sizeof(d));
    }

    bool insert(long long val) {
        for (int i = 30; i >= 0; i--)
            if (val & (1 << i)) {
                if (!d[i]) {
                    d[i] = val;
                    break;
                }
                val ^= d[i];
            }
        return val > 0;
    }

    int cnt() {
        int res = 0;
        for (int i = 30; i >= 0; --i) {
            if (d[i])res++;
        }
        return 1 << res;
    }
};

struct node {
    L_B lb;
    int lazy, w;
    int l, r;
} t[200004 * 4];

node merge(const node n1, const node n2) { //線性基合併
    node ret = n1;
    for (int i = 30; i >= 0; i--) {
        if (n1.lb.d[i])ret.lb.insert(n1.lb.d[i]);
        if (n2.lb.d[i])ret.lb.insert(n2.lb.d[i]);
    }
    ret.lb.insert(n1.w ^ n2.w);
    ret.w = n2.w;
    return ret;
}

int a[200004];

void pu(int rt) {// 線段樹更新
    int l = t[rt].l;
    int r = t[rt].r;
    int lazy = t[rt].lazy;
    t[rt] = merge(t[rt << 1], t[rt << 1 | 1]);
    t[rt].l = l, t[rt].r = r, t[rt].lazy = lazy;
}

void build(int rt, int l, int r) {
    t[rt].l = l, t[rt].r = r, t[rt].lazy = 0;
    t[rt].lb.init();
    if (l == r) {
        t[rt].w = a[l];
    } else {
        int mid = (l + r) >> 1;
        build(rt << 1, l, mid);
        build(rt << 1 | 1, mid + 1, r);
        pu(rt);
    }
}

void pushdown(int rt) {
    if (t[rt].lazy == 0)return;
    t[rt << 1].lazy ^= t[rt].lazy;
    t[rt << 1 | 1].lazy ^= t[rt].lazy;
    t[rt << 1].w ^= t[rt].lazy;
    t[rt << 1 | 1].w ^= t[rt].lazy;
    t[rt].lazy = 0;
}

void update(int rt, int l, int r, int xo) { // 區間更新
    if (t[rt].l >= l && t[rt].r <= r) {
        t[rt].lazy ^= xo;
        t[rt].w ^= xo;
    } else {
        pushdown(rt);
        int mid = (t[rt].l + t[rt].r) >> 1;
        if (l <= mid)update(rt << 1, l, r, xo);
        if (r > mid)update(rt << 1 | 1, l, r, xo);
        pu(rt);
    }
}

void query(int rt, int l, int r, node &ans) {
    if (t[rt].l >= l && t[rt].r <= r) {
        ans = merge(ans, t[rt]);
    } else {
        pushdown(rt);
        int mid = (t[rt].l + t[rt].r) >> 1;
        if (l <= mid) {
            query(rt << 1, l, r, ans);
        }
        if (r > mid) {
            query(rt << 1 | 1, l, r, ans);
        }
    }
}

int main() {
    int n, q;
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    build(1, 1, n);
    while (q--) {
        int op, l, r, k;
        scanf("%d", &op);
        if (op == 1) {
            scanf("%d%d%d", &l, &r, &k);
            update(1, l, r, k);
        } else {
            scanf("%d%d", &l, &r);
            node ans;
            ans.lb.init();
            ans.w = 0;
            query(1, l, r, ans);
            printf("%d\n", ans.lb.cnt());
        }
    }
}

原作者

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章