线性基+并查集
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 线段树分治 线性基 可撤销并查集