【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=4184
【题解】
以时间为下标建立线段树,每个数有一个存在时间区间,挂在对应线段树节点上。询问时维护一个线性基,dfs这颗线段树,在叶节点查询。
时间复杂度 O(31N∗logN) O ( 31 N ∗ l o g N )
【代码】
/* - - - - - - - - - - - - - - -
User : VanishD
problem : [bzoj4184]
Points : segment tree
- - - - - - - - - - - - - - - */
# include
# define ll long long
# define inf 0x3f3f3f3f
# define N 500010
# define K 31
using namespace std;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9'){ if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct Tree{
int pl, pr;
vector <int> q;
}T[N * 3];
struct Node{
int num[K];
int query(){
int tmp = 0;
for (int i = K - 1; i >= 0; i--)
if ((tmp ^ num[i]) > tmp)
tmp ^= num[i];
return tmp;
}
void extend(int tmp){
for (int i = K - 1; i >= 0; i--)
if ((tmp & (1 << i)) != 0){
if (num[i] != 0) tmp ^= num[i];
else {
num[i] = tmp;
return;
}
}
}
}now;
map <int, int> mp;
int place, L, R, ans[N], n, rt;
void extend(int &p, int data, int ql, int qr, int l, int r){
if (p == 0) p = ++place;
if (ql == l && qr == r){
T[p].q.push_back(data);
return;
}
int mid = (l + r) / 2;
if (mid >= qr) extend(T[p].pl, data, ql, qr, l, mid);
else if (mid < ql) extend(T[p].pr, data, ql, qr, mid + 1, r);
else extend(T[p].pl, data, ql, mid, l, mid), extend(T[p].pr, data, mid + 1, qr, mid + 1, r);
}
void query(int p, Node num, int l, int r){
if (p == 0){
int tmp = num.query();
for (int i = l; i <= r; i++)
ans[i] = tmp;
return;
}
for (unsigned i = 0; i < T[p].q.size(); i++)
num.extend(T[p].q[i]);
if (l == r){
ans[l] = num.query();
}
else {
int mid = (l + r) / 2;
query(T[p].pl, num, l, mid);
query(T[p].pr, num, mid + 1, r);
}
}
int main(){
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = read();
L = 1, R = n;
for (int i = 1; i <= n; i++){
int x = read();
if (x > 0) mp[x] = i;
else {
x = -x;
int l = mp[x], r = i - 1;
extend(rt, x, l, r, L, R);
mp[x] = 0;
}
}
map <int, int> :: iterator it = mp.begin();
while (it != mp.end()){
if ((*it).second != 0) extend(rt, (*it).first, (*it).second, n, L, R);
it++;
}
query(rt, now, L, R);
for (int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
return 0;
}