サマースクールキャンプオフ2019頭の牛より4 B-XOR(ベースリニア交差点)

質問の意味:

所与の\(\ N-)からの配列\(1 \)\(\ N-) および\(m個\)クエリ、各クエリすべて\([L、R] \ ) もし従属インターバル配列または\(X- \)

分析:

ため\([L、R] \ ) インターバル配列、排他的論理和か否かを判断することができる\(X \)は、決定することができる([L、R] \ \ ) 線形配列群間隔交差点、これは、次いで、交差点を決定することができる
ため\(N- \)インフラセグメントツリーの線形配列、葉とき線形ベース交差点押し上げについて行います。
線形断面を有するセグメントツリーを掲載は、挿入されたグループか否かが判断される\(X \)は、それがこのセクションを挿入することができるかを排他的ことを示す場合\(X \) 逆であってもよいです。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 50000 + 5;

struct Base {
    
    static const int maxN = 31;//int-31 or long long-62
    
    int tot, flag;
    int d[maxN + 5];
    int nd[maxN + 5];//used for kth
    
    Base() {
        tot = flag = 0;
        memset(d, 0, sizeof d);
        memset(nd, 0, sizeof nd);
    }

    bool ins(LL x) {
        for (int i = maxN; ~i; i--) {
            if (x & (1LL << i)) {
                if (d[i]) {
                    x ^= d[i];
                } else {
                    d[i] = x;
                    return true;
                }
            }
        }
        flag = 1;
        return false;
    }
    
    bool canIns(LL x) {
        for (int i = maxN; ~i; i--) {
            if (x & (1LL << i)) {
                if (d[i]) {
                    x ^= d[i];
                } else {
                    return true;
                }
            }
        }
        return false;
    }

    LL queryMax() {
        LL ans = 0;
        for (int i = maxN; ~i; i--) ans = max(ans, ans ^ d[i]);
        return ans;
    }

    LL queryMin() {
        for (int i = 0; i <= maxN; i++) if (d[i]) return d[i];
        return -1LL;
    }

    void rebuild() {
        for (int i = maxN; ~i; i--) {
            for (int j = i - 1; ~j; j--) {
                if (d[i] & (1LL << j)) d[i] ^= d[j];
            }
        }
        for (int i = 0; i <= maxN; i++) if (d[i])
                nd[tot++] = d[i];
    }

    LL kth(LL k) {
        if (flag) k--;
        if (!k) return 0LL;
        if (k >= (1LL << tot)) return -1LL;
        LL ans = 0;
        for (int i = maxN; ~i; i--) {
            if (k & (1LL << i)) ans ^= nd[i];
        }
        return ans;
    }

    void merge(Base b) {//与b取并集
        for (int i = maxN; ~i; i--) if (b.d[i])
                ins(b.d[i]);
    }

    Base mixed(Base B) {//与b取交集
        Base All, C, D;
    //  All.init(), C.init(), D.init();
        for (int i = maxN; ~i; i--) {
            All.d[i] = d[i];
            D.d[i] = 1LL << i;
        }
        for (int i = maxN; ~i; i--) {
            if (B.d[i]) {
                LL v = B.d[i], k = 0;
                bool can = true;
                for (int j = maxN; ~j; j--) {
                    if (v & (1LL << j)) {
                        if (All.d[j]) {
                            v ^= All.d[j];
                            k ^= D.d[j];
                        } else {
                            can = false;
                            All.d[j] = v;
                            D.d[j] = k;
                            break;
                        }
                    }
                }

                if (can) {
                    LL v = 0;
                    for (int j = maxN; ~j; j--) {
                        if (k & (1LL << j)) {
                            v ^= d[j];
                        }
                    }
                    C.ins(v);
                }
            }
        }
        return C;
    }

} lb[N << 2];

int n, m, sz, l, r, x;

void build(int rt, int l, int r) {
    if (l == r) {
        scanf("%d", &sz);
        for (int i = 1; i <= sz; i++) {
            scanf("%d", &x);
            lb[rt].ins(x);
        }
        return ;
    }
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    lb[rt] = lb[rt << 1].mixed(lb[rt << 1 | 1]);
}

bool query(int rt, int l, int r, int ql, int qr, int w) {
    if (l >= ql && r <= qr) {
        return !lb[rt].canIns(w);
    }
    int mid = l + r >> 1;
    if (ql <= mid && !query(rt << 1, l, mid, ql, qr, w)) return false;
    if (qr > mid && !query(rt << 1 | 1, mid + 1, r, ql, qr, w)) return false;
    return true;
}

int main() {
    scanf("%d %d", &n, &m);
    build(1, 1, n);
    while (m--) {
        scanf("%d %d %d", &l, &r, &x);
        if (x == 0) {
            puts("YES");
            continue;
        }
        if (query(1, 1, n, l, r, x)) puts("YES");
        else puts("NO");
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/ChaseNo1/p/11750086.html