题意:给你每个数字出现的时间和消失的时间,求每个时刻最大异或和
题解
按照时间建立线段树,线段树每个节点开个vector存一下这个时间区间有哪些数,然后递归进入的时候加入线性基,开一个栈记录一下加了哪些基底,回溯的时候把之前加的删掉即可
#include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) using namespace std; typedef long long ll; inline int read(){char c,p=0;int w; while(!isdigit(c=getchar()))if(c=='-')p=1;w=c&15; while(isdigit(c=getchar()))w=w*10+(c&15);return p?-w:w; } inline char smax(int&x,const int&y){return x<y?x=y,1:0;} inline char smin(int&x,const int&y){return x>y?x=y,1:0;} const int N=5e5+5,n=read(); vector<int>g[N<<2]; #define ls o<<1 #define rs o<<1|1 inline void ins(int o,int l,int r,int x,int y,int z){ if(x<=l&&r<=y){g[o].push_back(z);return;} int mid=l+r>>1; if(x<=mid)ins(ls,l,mid,x,y,z); if(y>mid)ins(rs,mid+1,r,x,y,z); } int p[33],s[33],top; inline void ins(int x){for(int i=31;~i;--i)if(x>>i&1)if(!p[i]){p[i]=x,s[++top]=i;break;}else x^=p[i];} inline void erase(int pre){while(top!=pre)p[s[top--]]=0;} inline void ask(int o,int l,int r){ int pre=top; for(int i=0;i<g[o].size();++i)ins(g[o][i]); if(l==r){ int ans=0; for(int i=31;~i;--i)smax(ans,ans^p[i]); return printf("%d\n",ans),erase(pre); } int mid=l+r>>1;ask(ls,l,mid),ask(rs,mid+1,r);erase(pre); } map<int,int>pos; map<int,int>::iterator it; int main(){ REP(i,1,n){ int x=read(); if(x>0)pos[x]=i; else{ it=pos.find(-x); ins(1,1,n,it->second,i-1,-x); pos.erase(it); } } for(it=pos.begin();it!=pos.end();++it) ins(1,1,n,it->second,n,it->first); ask(1,1,n); return 0; }
来源:https://www.cnblogs.com/HolyK/p/9884652.html