题意
给定时长 $n$ , 每个时刻有某个元素出现或者消失, 求每个时刻所有元素的最大异或值.
$n \le 500000$ .
分析
通过 map 或者 hash , 我们可以知道 $O(n)$ 个 "一个元素 $x$ 在 $[l, r]$ " 出现的信息.
对时间建立线段树, 每个节点开一个 vector , 对区间 $[l, r]$ 对应的所有节点插入一个 $x$ .
对线段树进行 DFS , 同时动态维护线性基.
实现
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <algorithm> #include <map> using namespace std; #define F(i, a, b) for (register int i = (a); i <= (b); i++) #define P(i, a, b) for (register int i = (a); i >= (b); i--) const int N = 1500000; const int E = 10000005; int n; map<int, int> vis; int M, tot, hd[N], nx[E], v[E]; int s[N], top, b[35]; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; } inline void Ins(int x, int w) { nx[++tot] = hd[x], hd[x] = tot, v[tot] = w; } inline void Fill(int L, int R, int w) { for (L--, R++, L += M, R += M; L^R^1; L >>= 1, R >>= 1) { if (!(L&1)) Ins(L^1, w); if (R&1) Ins(R^1, w); } } inline void Insert(int w) { P(i, 30, 0) if (w>>i&1) if (!b[i]) { b[s[++top] = i] = w; break; } else w ^= b[i]; } inline int Max(void) { int res = 0; P(i, 30, 0) res = max(res, res ^ b[i]); return res; } void Tsunami(int x, int L, int R) { if (R < 1 || L > n) return; int t = top; for (int k = hd[x]; k > 0; k = nx[k]) Insert(v[k]); if (L == R) printf("%d\n", Max()); else { int M = (L+R)>>1; Tsunami(x<<1, L, M); Tsunami(x<<1|1, M+1, R); } for (; top > t; s[top--] = 0) b[s[top]] = 0; } int main(void) { #ifndef ONLINE_JUDGE freopen("bzoj4184.in", "r", stdin); freopen("bzoj4184.out", "w", stdout); #endif n = rd(); for (M = 1; M < n+2; M <<= 1); F(i, 1, n) { int x = rd(); if (x > 0) vis[x] = i; else x = -x, Fill(vis[x], i-1, x), vis[x] = 0; } for (map<int, int>::iterator it = vis.begin(); it != vis.end(); it++) if (it -> second > 0) Fill(it -> second, n, it -> first); Tsunami(1, 0, M-1); return 0; }
时间: 2024-10-12 03:15:27