BZOJ3489:A simple rmq Problem
阿新 • • 發佈:2018-12-29
淺談主席樹: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; }