[]BZOJ4184: shallot
题解: 考虑离线 对于每个数都有一个存在时间段 我们以时间段建线段树 因为线性基不允许删除元素 然后我们只需要把对应时间段的元素加入 这样就能避免删除问题 然后就是普通操作了(第一次写链表版本的线性基 学到了学到了!!!!!
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=5e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } vector<int>vec[MAXN<<2]; void Join(int x,int t){ for(int i=0;i<vec[x].size();i++)if(t>(vec[x][i]^t))t^=vec[x][i]; if(t){ vec[x].pb(t); int sz=vec[x].size()-1; for(int i=sz;i>=1;i--)if(vec[x][i]>vec[x][i-1])swap(vec[x][i],vec[x][i-1]); } } void merge(vector<int> &v,int x){ for(int i=0;i<vec[x].size();i++){ int t=vec[x][i]; for(int j=0;j<v.size();j++)if(t>(v[j]^t))t^=v[j]; if(t){ v.pb(t); int sz=v.size()-1; for(int j=sz;j>=1;j--)if(v[j]>v[j-1])swap(v[j],v[j-1]); } } } void get_max(vector<int> v){ int ans=0; for(int i=0;i<v.size();i++)if(ans<(ans^v[i]))ans^=v[i]; printf("%d\n",ans); } void update(int rt,int l,int r,int ql,int qr,int t){ if(ql<=l&&r<=qr){Join(rt,t);return ;} int mid=(l+r)>>1; if(ql<=mid)update(rt<<1,l,mid,ql,qr,t); if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,t); } void query(int rt,int l,int r,vector<int> v){ merge(v,rt); if(l==r){get_max(v);return ;} int mid=(l+r)>>1; query(rt<<1,l,mid,v); query(rt<<1|1,mid+1,r,v); } set<pair<int,int> >s; set<pair<int,int> >::iterator ite; int main(){ int n=read();int t; inc(i,1,n){ t=read(); if(t>0)s.insert(mp(t,i)); else{ ite=s.lower_bound(mp(t*-1,0)); update(1,1,n,(*ite).second,i-1,-t); s.erase(ite); } } for(ite=s.begin();ite!=s.end();ite++)update(1,1,n,(*ite).second,n,(*ite).first); query(1,1,n,vec[0]); return 0; }
4184: shallot
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 914 Solved: 433
[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