题解[P4585火星商店问题]

原题链接
题面过长含糊不清差评
震惊!这题竟没有树状数组套可持久化 \(01trie\) 的题解,补一发。
思路极其简单,由于查询相当于是时间与标号两维限制下求与某个数的异或最大值。
那就可以对时间限制用一个树状数组解决,标号在每个时间下用一颗可持久化 \(01trie\) 就没了。
具体询问时要把树状数组对应时间上标号合法的根拎出来,相当于在时间、标号上都用一次差分。
在找 \(01trie\) 上合法标号的根可以在每个时间上开一个 \(multiset\) ,用 \(lowerbound\) 以及 \(upperbound\) 解决。
还有所谓的特殊商品直接无脑再写一个可持久化 \(01trie\) 取最大值即可。
时间复杂度是 \(O((n+m)\times log(n)^2)\) 的。
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=3.5e7+10,K=18;
int n,m,x,y,tt,tot,res,ans;
int a[N],rt[N];
struct inq{int opt,l,r,x,d,t;}q[N];
struct trie{int s[2],sz;}t[M];
void update(int &k,int kk,int x,int i){
	k=++tot;t[k]=t[kk];t[k].sz++;if(i<0)return;
	bool b=x&(1<<i);update(t[k].s[b],t[kk].s[b],x,i-1);
}
struct node{
	int i,x;mutable int rt; 
	node(int _i,int _x=0):i(_i),x(_x){};
	bool operator <(const node &x)const{return i<x.i;};
};
int lowbit(int x){return x&(-x);}
int p[N][2];multiset<node>s[N];
#define msit multiset<node>::iterator
#define f0 for(int i=1;i<=p[0][0];i++)
#define f1 for(int i=1;i<=p[0][1];i++)
void pre_update(int pos,int id,int x){
	for(int i=pos;i<=tt;i+=lowbit(i))s[i].insert(node(id,x));
}
void update(){
	for(int i=1;i<=tt;i++){
		int pre=0;
		s[i].insert(node(0,0));//不塞一个空的进去在lower_bound时会出问题 
		for(msit j=s[i].begin();j!=s[i].end();j++)
			update(j->rt,pre,j->x,K),pre=j->rt;
	}
}
void inquiry_pre(int l,int r,int pos,bool b){
	for(int i=pos;i;i-=lowbit(i)){
		msit l1=s[i].lower_bound(node(l));
		if(l1==s[i].end())continue;l1--;
		msit r1=s[i].upper_bound(node(r));r1--;
		p[++p[0][b]][b]=r1->rt,p[++p[0][b^1]][b^1]=l1->rt;
	}
}
void inquiry(int x,int k){
	if(k<0)return;int tmp=0;bool b=x&(1<<k);
	f1 tmp+=t[t[p[i][1]].s[b^1]].sz;f0 tmp-=t[t[p[i][0]].s[b^1]].sz;
	if(tmp){res+=1<<k;f0 p[i][0]=t[p[i][0]].s[b^1];f1 p[i][1]=t[p[i][1]].s[b^1];inquiry(x,k-1);}
	else {f0 p[i][0]=t[p[i][0]].s[b];f1 p[i][1]=t[p[i][1]].s[b];inquiry(x,k-1);}
}
void inquiry(int k1,int k2,int x,int k){
	if(k<0)return;bool b=x&(1<<k);
	int tmp=t[t[k2].s[b^1]].sz-t[t[k1].s[b^1]].sz;
	if(tmp)res+=1<<k,inquiry(t[k1].s[b^1],t[k2].s[b^1],x,k-1);
	else inquiry(t[k1].s[b],t[k2].s[b],x,k-1);
}
void inquiry_(int l,int r,int tl,int tr,int x){
	p[0][0]=p[0][1]=0;
	inquiry_pre(l,r,tr,1);
	inquiry_pre(l,r,tl-1,0);
	inquiry(x,K);
}
main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&x),update(rt[i],rt[i-1],x,K);
	for(int i=1;i<=m;i++){
		scanf("%d",&q[i].opt);
		if(q[i].opt)scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].x,&q[i].d);
		else scanf("%d%d",&q[i].l,&q[i].x),++tt;
		q[i].t=tt;
	}
	for(int i=1;i<=m;i++)if(!q[i].opt)pre_update(q[i].t,q[i].l,q[i].x);update();
	for(int i=1;i<=m;i++)if(q[i].opt){
		if(q[i].d&&q[i].t)inquiry_(q[i].l,q[i].r,max(q[i].t-q[i].d+1,1),q[i].t,q[i].x);
		ans=res,res=0;inquiry(rt[q[i].l-1],rt[q[i].r],q[i].x,K);ans=max(ans,res);
		printf("%d\n",ans);res=ans=0;
	}
}
posted @ 2021-07-25 20:00  Y_B_X  阅读(30)  评论(0编辑  收藏  举报