线性基
有一个显然的线段树套线性基的做法,但是会T
考虑优化,维护线性基的时候,考虑这个数出现的位置,如果加入的数比当前的数位置靠后,那么替换,用之前的数向下继续做
查询的时候和位置比较一下再加入
#include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 5; int n, m; int pos[maxn][32], v[maxn][32]; void add(int x, int c, int p) { for(int i = 30; ~i; --i) if(x >> i & 1) { if(!v[c][i]) { v[c][i] = x; pos[c][i] = p; break; } else { if(p > pos[c][i]) { swap(pos[c][i], p); swap(x, v[c][i]); } x ^= v[c][i]; } } } int query(int l, int r) { int ret = 0; for(int i = 30; ~i; --i) if(pos[r][i] >= l && (ret ^ v[r][i]) > ret) ret ^= v[r][i]; return ret; } int main() { int T; scanf("%d", &T); while(T--) { int ans = 0; memset(v, 0, sizeof(v)); memset(pos, 0, sizeof(pos)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) { int x; scanf("%d", &x); for(int j = 0; j < 31; ++j) { v[i][j] = v[i - 1][j]; pos[i][j] = pos[i - 1][j]; } add(x, i, i); } while(m--) { int opt, l, r, x; scanf("%d", &opt); if(opt == 0) { scanf("%d%d", &l, &r); l = (l ^ ans) % n + 1; r = (r ^ ans) % n + 1; if(l > r) swap(l, r); printf("%d ", ans = query(l, r)); } if(opt == 1) { scanf("%d", &x); x ^= ans; ++n; for(int i = 0; i < 31; ++i) { v[n][i] = v[n - 1][i]; pos[n][i] = pos[n - 1][i]; } add(x, n, n); } } } return 0; }