P4585 [FJOI2015]火星商店问题

P4585 [FJOI2015]火星商店问题

线段树+可持久化01Trie。

首先区间的限制很容易想到线段树,然后异或最大值很明显就是可持久化 01 Trie,于是可以维护,至于 d 天内的限制,我们插入 01Trie 的时候打一个时间 \(tag\) ,询问的时候看一下满不满足就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=1e5+5,M=5e7+5,INF=0x3f3f3f3f;
int n,m,d,cnt,a[N];
int tr[M][2],tag[M][2],root[N<<2];
struct SegMentTree{
	int l,r;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
}tree[N<<2];
void Insert(int p,int val,int t){
	for(int i=1<<18;i;i>>=1){
		bool ch=val&i;
		if(!tr[p][ch])tr[p][ch]=++cnt;
		tag[p][ch]=max(t,tag[p][ch]);
		p=tr[p][ch];
	}
	return ;
}
int Ask(int p,int val,int t){
	int res=0;
	for(int i=1<<18;i;i>>=1){
		bool ch=val&i;
		if(tr[p][ch^1]&&tag[p][ch^1]>=t)res|=i,p=tr[p][ch^1];
		else if(tr[p][ch]&&tag[p][ch]>=t)p=tr[p][ch];
	}
	return res;
}
void Build(int x,int l,int r){
	l(x)=l,r(x)=r;
	root[x]=++cnt;
	for(int i=l;i<=r;i++) Insert(root[x],a[i],INF);
	if(l==r)return;
	int mid=(l+r)>>1;
	Build(x<<1,l,mid);
	Build(x<<1|1,mid+1,r);
	return ;
}
void Modify(int x,int pos,int val,int t){
	int l=l(x),r=r(x);
	Insert(root[x],val,t);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid) Modify(x<<1,pos,val,t);
	else Modify(x<<1|1,pos,val,t);
	return ;
}
int Query(int x,int L,int R,int val,int t){
	int l=l(x),r=r(x);
	if(L<=l&&r<=R)return Ask(root[x],val,t);
	int mid=(l+r)>>1,res=0;
	if(L<=mid) res=max(res,Query(x<<1,L,R,val,t));
	if(R>mid) res=max(res,Query(x<<1|1,L,R,val,t));
	return res;
}
int main(){
	read(n),read(m);
	for(int i=1;i<=n;i++) read(a[i]);
	Build(1,1,n);
	while(m--){
		int op;
		read(op);
		if(!op){
			int pos,val;d++;
			read(pos),read(val);
			Modify(1,pos,val,d);
		}
		else{
			int l,r,x,t;
			read(l),read(r),read(x),read(t);
			write(Query(1,l,r,x,d-t+1)),puts("");
		}
	}
	return 0;
}

这道题也可以线段树分治+可持久化 01 Trie,我们发现每一个商品对于询问有一个生效区间,于是线段树分治。

好像还有 CDQ分治 的神奇做法。

posted @ 2021-04-22 16:21  __Anchor  阅读(90)  评论(0编辑  收藏  举报