【tmp】线段树按时间分治

例题传送门

  其实就是把每个价值往存在的时间区间里面丢,线段树上每个节点存这个节点代表的区间有哪些值,注意是存在最大的完全包含区间内

(也有线性基啦qwq)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=5*(1e5)+1,TOP=30,SEG=MAXN*2;
int ed[MAXN],st[MAXN];
int a[MAXN],b[MAXN],id[MAXN];
int ans[MAXN],cnt[MAXN];
int n,m;
struct xxj{/*{{{*/
	int a[TOP+1];
	void init(){memset(a,0,sizeof(a));}
	bool insert(int x){
		for (int i=TOP;i>=0;--i){
			if (x&(1<<i)){
				if (!a[i]){
					a[i]=x;
					break;
				}
				x^=a[i];
			}
		}
		return x>0;
	}
	int query_max(){
		int ret=0;
		for (int i=TOP;i>=0;--i)
			if ((ret^a[i])>ret) ret^=a[i];
		return ret;
	}
	void merge(xxj x){
		for (int i=TOP;i>=0;--i)
			if (x.a[i])
				insert(x.a[i]);
	}
};/*}}}*/
namespace Seg{/*{{{*/
	int ch[SEG][2];
	int tot,n;
	vector<int> rec[SEG];
	void _build(int x,int l,int r){
		if (l==r) return;
		int mid=l+r>>1;
		ch[x][0]=++tot; _build(ch[x][0],l,mid);
		ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
	}
	void build(int _n){n=_n; tot=1; _build(1,1,n);}
	void _update(int x,int l,int r,int lx,int rx,int delta){
		if (l<=lx&&rx<=r){
			rec[x].push_back(delta);
			return;
		}
		int mid=lx+rx>>1;
		if (l>mid) _update(ch[x][1],l,r,mid+1,rx,delta);
		else if (r<=mid) _update(ch[x][0],l,r,lx,mid,delta);
		else{
			_update(ch[x][0],l,mid,lx,mid,delta);
			_update(ch[x][1],mid+1,r,mid+1,rx,delta);
		}
	}
	void update(int l,int r,int delta){_update(1,l,r,1,n,delta);}
	void _query(int x,int lx,int rx,xxj now){
		for (int i=0;i<rec[x].size();++i)
			now.insert(rec[x][i]);
		if (lx==rx){
			ans[lx]=now.query_max();
			return;
		}
		int mid=lx+rx>>1;
		_query(ch[x][0],lx,mid,now);
		_query(ch[x][1],mid+1,rx,now);
	}
	void solve(){xxj now; now.init();_query(1,1,n,now);}
}/*}}}*/
void prework();
int Abs(int x){return x<0?-x:x;}

int main(){
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
#endif
	int x;
	scanf("%d",&n);
	for (int i=1;i<=n;++i) scanf("%d",a+i),b[i]=Abs(a[i]);
	prework();
	Seg::build(n);
	for (int i=1;i<=n;++i)
		if (a[i]>0){
			++cnt[id[i]];
			if (cnt[id[i]]==1)
				st[id[i]]=i;
		}
		else{
			--cnt[id[i]];
			if (cnt[id[i]]==0){
				Seg::update(st[id[i]],i-1,-a[i]);
				st[id[i]]=0;
			}
		}
	for (int i=1;i<=n;++i)
		if (st[id[i]]) 
			Seg::update(st[id[i]],n,Abs(a[i])),st[id[i]]=0;
	Seg::solve();
	for (int i=1;i<=n;++i)
		printf("%d\n",ans[i]);
}

void prework(){
	sort(b+1,b+1+n);
	unique(b+1,b+1+n);
	for (int i=1;i<=n;++i){
		id[i]=Abs(a[i]);
		id[i]=lower_bound(b+1,b+1+n,id[i])-b;
	}
}
posted @ 2018-04-16 16:49  yoyoball  阅读(145)  评论(0)    收藏  举报