线性基+并查集

Posted fanshhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性基+并查集相关的知识,希望对你有一定的参考价值。

线性基+并查集

无效位置

#include <cstdio>
#include <cstring>
typedef long long LL;
LL ans[1000010], a[1000010], b[1000010], d[1000010][70], pre[1000010];
int findn(int x) {
    int p = x, tmp;
    while(x != pre[x]) x = pre[x];
    while(p != x) {
        tmp = pre[p];
        pre[p] = x;
        p = tmp;
    }
    return x;
}
void add(int x, int y) {
    int p = findn(x);
    int q = findn(y);
    if(p != q) pre[q] = p;
}
void ins(LL d[][70], int tmp, int x) {
    for(int j = 60; j >= 0; j--) {
        if(a[x] & (1LL << j)) {
            if(d[tmp][j]) a[x] ^= d[tmp][j];
            else {
                d[tmp][j] = a[x];
                break;
            }
        }
    }
}
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for(int i = 1; i <= n; i++) scanf("%lld", &b[i]);
    memset(pre, 0, sizeof(pre));
    LL maxn = 0;
    for(int i = n; i > 0; i--) {
        int x = b[i];
        pre[x] = x;
        if(pre[x-1] && pre[x+1]) {
            int tmp = findn(x-1);
            ins(d, tmp, x);
            add(x-1, x);
            int tmp1 = findn(x+1);
            add(x, x + 1);
            int tmp2 = findn(x);
            for(int j = 60; j >= 0; j--) {
                for(int k = 60; k >= 0; k--) {
                    if(d[tmp1][j] & (1LL << k)) {
                        if(d[tmp2][k]) d[tmp1][j] ^= d[tmp2][k];
                        else {
                            d[tmp2][k] = d[tmp1][j];
                            break;
                        }
                    }
                }
            }
        }
        else if(pre[x-1] && pre[x+1] == 0) {
            int tmp = findn(x-1);
            ins(d, tmp, x);
            add(x-1, x);
        }
        else if(pre[x-1] == 0 && pre[x+1]) {
            int tmp = findn(x+1);
            add(x+1, x);
            ins(d, tmp, x);
        }
        else {
            ins(d, x, x);
        }
        int tmp = findn(x);
        LL sum = 0;
        for(int j = 60; j >= 0; j--) {
            if((sum ^ d[tmp][j]) > sum) {
                    sum ^= d[tmp][j];
            }
        }
        if(sum > maxn) maxn = sum;
        ans[i] = maxn;
    }
    for(int i = 1; i <= n; i++) printf("%lld
", ans[i]);
    return 0;
}

以上是关于线性基+并查集的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 938G 线段树分治 线性基 可撤销并查集

loj6198谢特 后缀数组+并查集+Trie

棋盘上的守卫 并查集模拟外向基环树

并查集入门

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

10.23