洛谷P4585/bzoj4137 火星商店问题 线段树+可持久化trie树

题目分析

首先特殊商品显然可持久化trie树一波就行了。

至于非特殊商品呢?时间线段树套可持久化trie?

注意到本题没有要求强制在线,所以并不需要套呗。

把询问都落到时间线段树的区间上(用vector存),然后将所有添加商品事件都按照商店编号排序。

递归遍历时间线段树,遍历到一个区间(线段树的一个节点)时,将这个区间的所有添加商品事件建立可持久化trie树。然后处理这个节点上的所有询问。

代码

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
	int q=0;char ch=' ';
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
	return q;
}
const int N=100005,D=16;
int n,m,SZ,tim,Q;
int bin[17],rt[N],ans[N],st[N];
struct question{int l,r,tl,tr,x;}q[N];
struct event{int id,v,t;}e[N],e1[N],e2[N];
struct node{int s[2],sz;}tr[N*18];
bool cmp(event a,event b) {return a.id<b.id;}

void ins(int &x,int y,int num,int d) {
	x=++SZ,tr[x]=tr[y],++tr[x].sz;
	if(d==-1) return;
	int t=((num&bin[d])==0?0:1);
	ins(tr[x].s[t],tr[y].s[t],num,d-1);
}
int query(int x,int y,int num,int d) {
	if(d==-1) return 0;
	int t=((num&bin[d])==0?0:1);
	if(tr[tr[y].s[t^1]].sz-tr[tr[x].s[t^1]].sz)
		return query(tr[x].s[t^1],tr[y].s[t^1],num,d-1)+bin[d];
	else return query(tr[x].s[t],tr[y].s[t],num,d-1);
}

vector<int> orz[N<<2];
void putdown(int l,int r,int s,int t,int i,int id) {
	if(l>r) return;
	if(l<=s&&t<=r) {orz[i].push_back(id);return;}
	int mid=(s+t)>>1;
	if(l<=mid) putdown(l,r,s,mid,i<<1,id);
	if(mid+1<=r) putdown(l,r,mid+1,t,(i<<1)|1,id);
}
void work(int l,int r,int k) {
	SZ=0;int top=0,js1=0,js2=0,mid=(l+r)>>1;
	for(RI i=l;i<=r;++i)
		st[++top]=e[i].id,ins(rt[top],rt[top-1],e[i].v,D);
	for(RI i=0;i<orz[k].size();++i) {
		int tmp=orz[k][i];
		int l=lower_bound(st+1,st+1+top,q[tmp].l)-st;
		int r=upper_bound(st+1,st+1+top,q[tmp].r)-st-1;
		ans[tmp]=max(ans[tmp],query(rt[l-1],rt[r],q[tmp].x,D));
	}
	if(l==r) return;
	for(RI i=l;i<=r;++i)
		if(e[i].t<=mid) e1[++js1]=e[i];
		else e2[++js2]=e[i];
	for(RI i=1;i<=js1;++i) e[l+i-1]=e1[i];
	for(RI i=1;i<=js2;++i) e[l+js1-1+i]=e2[i];
	work(l,mid,k<<1),work(mid+1,r,(k<<1)|1);
}
int main()
{
	int op,l,r,x,d;
	n=read(),m=read();
	bin[0]=1;for(RI i=1;i<=D;++i) bin[i]=bin[i-1]<<1;
	for(RI i=1;i<=n;++i) x=read(),ins(rt[i],rt[i-1],x,D);
	tim=1;
	for(RI i=1;i<=m;++i) {
		op=read();
		if(op) {
			l=read(),r=read(),x=read(),d=read();
			q[++Q]=(question){l,r,max(1,tim-d+1),tim,x};
			ans[Q]=query(rt[l-1],rt[r],x,D);
		}
		else e[++tim]=(event){read(),read(),tim};
	}
	for(RI i=1;i<=Q;++i) putdown(q[i].tl,q[i].tr,1,tim,1,i);
	sort(e+1,e+1+tim,cmp);
	work(1,tim,1);
	for(RI i=1;i<=Q;++i) printf("%d\n",ans[i]);
	return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/litble/article/details/84997321
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞