BZOJ3489:A simple rmq problem

浅谈主席树:https://www.cnblogs.com/AKMer/p/9956734.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3489

题目意思就是在线求\(pos\)\([l,r]\)\(lst\)\([0,l-1]\)\(nxt\)\([r+1,n+1]\)的点中权值最大的。其中\(pos\)表示这个点的下标,\(lst\)表示上一个跟这个点相同的点的下标,\(nxt\)表示下一个跟这个点相同的点的下标。

这样子就变成求立方体最大点值了,我们可以果断树套树套树走一波,然后获得\(TLE\)的好成绩。

所以我们得用一些神奇的手段降低问题的维度。

而这个手段就是可持久化。

我们按\(lst\)从小到大在\(nxt\)值域范围内建立可持久化线段树,内套位置线段树维护区间最大值即可。

时间复杂度:\(O(nlog^2n)\)

空间复杂度:\(O(nlog^2n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=1e5+5;

int n,m,lstans;
int rt[maxn],tmp[maxn];
int pos[maxn],a[maxn],lst[maxn],nxt[maxn];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

struct Project {
	int lst,nxt,pos,val;

	Project() {}

	Project(int _lst,int _nxt,int _pos,int _val) {
		lst=_lst,nxt=_nxt,pos=_pos,val=_val;
	}

	bool operator<(const Project &a)const {
		return lst<a.lst;
	}
}p[maxn];

struct pos_chairman_tree {
	int tot;
	struct tree_node {
		int ls,rs,mx;
	}tree[maxn*18*18];

	void change(int &p,int lst,int l,int r,Project node) {
		p=++tot;tree[p]=tree[lst];
		tree[p].mx=max(tree[p].mx,node.val);
		if(l==r)return;
		int mid=(l+r)>>1;
		if(node.pos<=mid)change(tree[p].ls,tree[lst].ls,l,mid,node);
		else change(tree[p].rs,tree[lst].rs,mid+1,r,node);
	}

	int query(int p,int l,int r,int L,int R) {
		if(L<=l&&r<=R)return tree[p].mx;
		int mid=(l+r)>>1,res=0;
		if(L<=mid)res=max(res,query(tree[p].ls,l,mid,L,R));
		if(R>mid)res=max(res,query(tree[p].rs,mid+1,r,L,R));
		return res;
	}
}T2;

struct lst_chairman_tree {
	int tot;
	struct tree_node {
		int ls,rs,rt;
	}tree[maxn*18];

	void change(int &p,int lst,int l,int r,Project node) {
		p=++tot;tree[p]=tree[lst];
		T2.change(tree[p].rt,tree[lst].rt,1,n,node);
		if(l==r)return;
		int mid=(l+r)>>1;
		if(node.nxt<=mid)change(tree[p].ls,tree[lst].ls,l,mid,node);
		else change(tree[p].rs,tree[lst].rs,mid+1,r,node);
	}

	int query(int p,int l,int r,int L,int R) {
		if(!p)return 0;
		if(l>R)return T2.query(tree[p].rt,1,n,L,R);
		int mid=(l+r)>>1,res=query(tree[p].rs,mid+1,r,L,R);
		if(R+1<=mid)res=max(res,query(tree[p].ls,l,mid,L,R));
		return res;
	}
}T1;

int main() {
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),lst[i]=pos[a[i]],pos[a[i]]=i;
	for(int i=1;i<=n;i++)pos[i]=n+1;
	for(int i=n;i;i--)nxt[i]=pos[a[i]],pos[a[i]]=i;
	for(int i=1;i<=n;i++)p[i]=Project(lst[i],nxt[i],i,a[i]);
	sort(p+1,p+n+1);
	for(int i=1;i<=n;i++) {
		tmp[i]=p[i].lst;
		T1.change(rt[i],rt[i-1],2,n+1,p[i]);
	}
	for(int i=1;i<=m;i++) {
		int l=(read()+lstans)%n+1,r=(read()+lstans)%n+1;
		if(r<l)swap(l,r);
		int pos=lower_bound(tmp+1,tmp+n+1,l)-tmp-1;
		lstans=T1.query(rt[pos],2,n+1,l,r);
		printf("%d\n",lstans);
	}
	return 0;
}
posted @ 2018-12-29 19:22  AKMer  阅读(207)  评论(0编辑  收藏  举报