[BZOJ4137][FJOI2015]火星商店问题

luogu

description

有若干个\(\mbox{vector}\),支持单点\(\mbox{push_back}\),以及询问最近\(d\)\(\mbox{push_back}\)操作中在区间\([l,r]\)内的数与\(k\)的异或最大值。
所有数\(\le10^5\)

sol

开一棵线段树,每个节点是一棵\(\mbox{Trie}\)树,这样就可以查异或最大值了。
怎么处理时间的限制呢?在\(\mbox{Trie}\)树的每个节点维护一下这个节点的最新更新时间,查询的时候如果这个最新更新时间大于一个和\(d\)有关的限制就表示可以往这个子树走,否则就不行。

然后这样子据说会\(MLE\)
所以就把所有修改个询问都挂链挂到每个线段树的节点上,再离线线段树分治,这样空间复杂度就可以优化到\(O(n\log n)\)

code

我不管反正我就是写在线做法。
洛谷过了,然后\(BZ\)的数据本地测过了。别的我不管qwq。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 1e5+5;
int n,m,tim,ch[2][N*100],val[N*100],R[N],rt[N<<2],tot,ans;
void mdf1(int &x,int p,int dep){
	++tot;ch[0][tot]=ch[0][x];ch[1][tot]=ch[1][x];
	val[tot]=val[x]+1;x=tot;if (!~dep) return;
	mdf1(ch[(p>>dep)&1][x],p,dep-1);
}
int qry1(int x,int y,int p,int dep){
	if (!~dep) return 0;int c=~(p>>dep)&1;
	if (val[ch[c][x]]-val[ch[c][y]]) return qry1(ch[c][x],ch[c][y],p,dep-1)|(1<<dep);
	c^=1;return qry1(ch[c][x],ch[c][y],p,dep-1);
}
void mdf2(int &x,int p,int dep,int t){
	if (!x) x=++tot;val[x]=t;if (!~dep) return;
	mdf2(ch[(p>>dep)&1][x],p,dep-1,t);
}
int qry2(int x,int p,int dep,int t){
	if (!~dep) return 0;int c=~(p>>dep)&1;
	if (val[ch[c][x]]>t) return qry2(ch[c][x],p,dep-1,t)|(1<<dep);
	c^=1;return qry2(ch[c][x],p,dep-1,t);
}
void modify(int x,int l,int r,int p,int v,int t){
	mdf2(rt[x],v,16,t);
	if (l==r) return;int mid=l+r>>1;
	if (p<=mid) modify(x<<1,l,mid,p,v,t);
	else modify(x<<1|1,mid+1,r,p,v,t);
}
void query(int x,int l,int r,int ql,int qr,int v,int t){
	if (l>=ql&&r<=qr) {ans=max(ans,qry2(rt[x],v,16,t));return;}
	int mid=l+r>>1;
	if (ql<=mid) query(x<<1,l,mid,ql,qr,v,t);
	if (qr>mid) query(x<<1|1,mid+1,r,ql,qr,v,t);
}
int main(){
	n=gi();m=gi();
	for (int i=1;i<=n;++i) mdf1(R[i]=R[i-1],gi(),16);
	for (int i=1;i<=m;++i)
		if (gi()){
			int l=gi(),r=gi(),v=gi(),d=gi();
			ans=qry1(R[r],R[l-1],v,16);
			query(1,1,n,l,r,v,tim-d);printf("%d\n",ans);
		}else{
			int p=gi(),v=gi();
			modify(1,1,n,p,v,++tim);
		}
	return 0;
}
posted @ 2018-07-29 16:55  租酥雨  阅读(349)  评论(1编辑  收藏  举报