4184: shallot
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 263 Solved: 129
[ Submit][ Status][ Discuss]
Description
小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏。
每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且
让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大。
这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为Oi选手的你,你能帮帮他吗?
你只需要输出最大的异或和即可,若小葱手中没有小葱苗则输出0。
Input
第一行一个正整数n表示总时间;第二行n个整数a1,a2...an,若ai大于0代表给了小葱一颗数字为ai的小葱苗,否则代表从小葱手中拿走一颗数字为-ai的小葱苗。
Output
输出共n行,每行一个整数代表第i个时刻的最大异或和。
Sample Input
6
1 2 3 4 -2 -3
1 2 3 4 -2 -3
Sample Output
1
3
3
7
7
5
3
3
7
7
5
HINT
N<=500000,Ai<=2^31-1
Source
按线段树分治
每一个数字可以对应到线段树中的log个区间,在这些区间里面插入这个数字
对于线段树执行dfs
对于线段树每层,与上一层留下的基搞一搞再更新出新的基,然后一直往下走就行了
嗯。。。这个新增xor线性基是可以直接和上一层留下的东西操作后出来的,
不用每层再重新算。。不然常数太大了
然后那个保留基的f数组,,完全可以用深度来存,以便递归回来时及时腾出空间,不用每个节点都设一个
MLE + TLE....GG
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 5E5 + 50;
const int T = 8;
int n,m,cur = 1,a[maxn],b[maxn],f[40][31];
vector <int> v[maxn*T];
vector <int> p[maxn];
void Work(int o,int l,int r,int D)
{
for (int i = 0; i < v[o].size(); i++) {
int x = v[o][i];
for (int j = 30; j >= 0; j--)
if ((x>>j)&1) {
if (!f[D][j]) {
f[D][j] = x;
break;
}
x ^= f[D][j];
}
}
if (l == r) {
int ans = 0;
for (int i = 30; i >= 0; i--)
if ((ans ^ f[D][i]) > ans) ans ^= f[D][i];
printf("%d\n",ans);
return;
}
int mid = (l + r) >> 1;
for (int i = 0; i < 31; i++) f[D+1][i] = f[D][i];
Work(o<<1,l,mid,D+1);
for (int i = 0; i < 31; i++) f[D+1][i] = f[D][i];
Work(o<<1|1,mid+1,r,D+1);
}
void Insert(int o,int l,int r,int ql,int qr,int k)
{
if (ql <= l && r <= qr) {
v[o].push_back(k);
return;
}
int mid = (l + r) >> 1;
if (ql <= mid) Insert(o<<1,l,mid,ql,qr,k);
if (qr > mid) Insert(o<<1|1,mid+1,r,ql,qr,k);
}
int getint()
{
char ch = getchar();
int ret = 0,A = 1;
while (ch < '0' || '9' < ch) {
if (ch == '-') A = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret*A;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n; int tot = 0;
for (int i = 1; i <= n; i++) {
b[i] = getint();
if (b[i] > 0) a[++tot] = b[i];
}
sort(a + 1,a + tot + 1);
for (int i = 2; i <= n; i++)
if (a[i] != a[i-1])
a[++cur] = a[i];
for (int i = n; i >= 1; i--)
if (b[i] < 0) {
int po = lower_bound(a + 1,a + cur + 1,-b[i]) - a;
p[po].push_back(i);
}
for (int i = 1; i <= n; i++)
if (b[i] > 0) {
int Last = n;
int po = lower_bound(a + 1,a + cur + 1,b[i]) - a;
if (p[po].size())
Last = p[po][p[po].size()-1] - 1,p[po].pop_back();
Insert(1,1,n,i,Last,b[i]);
}
Work(1,1,n,1);
return 0;
}