题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489
题意:一个数列。每次询问一个区间内出现一次的最大的数字是多少。
思路:设last[i]表示i位置的数字上一次出现的位置,next[i]类似。那么询问区间[L,R]时,这个区间的哪些数字可以只出现一次呢?是那些last值小于L且next值大于R的数字。因此按照last排序后,按照last可持久化。具体看代码吧 不好说
const int N=100005; struct node { int val,last,next,id; }; node b[N]; int last[N],next[N],n,m; struct Node1 { int Max; int L,R; }; struct Node2 { int root; int L,R; }; Node1 A[40000005]; Node2 a[N*20]; int ANum,aNum; int cmp(node a,node b) { return a.last<b.last; } int root[N]; void insert1(int &t,int L,int R,int pos,int val) { int cur=++ANum; A[cur]=A[t]; t=cur; A[t].Max=max(A[t].Max,val); if(L==R) return; int M=(L+R)>>1; if(pos<=M) insert1(A[t].L,L,M,pos,val); else insert1(A[t].R,M+1,R,pos,val); } void insert(int &t,int L,int R,int posX,int posY,int val) { int cur=++aNum; a[cur]=a[t]; t=cur; insert1(a[t].root,1,n,posY,val); if(L==R) return; int M=(L+R)>>1; if(posX<=M) insert(a[t].L,L,M,posX,posY,val); else insert(a[t].R,M+1,R,posX,posY,val); } int query1(int t,int L,int R,int ll,int rr) { if(!t) return 0; if(L==ll&&R==rr) return A[t].Max; int M=(L+R)>>1; if(rr<=M) return query1(A[t].L,L,M,ll,rr); if(ll>M) return query1(A[t].R,M+1,R,ll,rr); int ans1=query1(A[t].L,L,M,ll,M); int ans2=query1(A[t].R,M+1,R,M+1,rr); return max(ans1,ans2); } int query(int t,int L,int R,int ll,int rr,int ll1,int rr1) { if(L==ll&&R==rr) return query1(a[t].root,1,n,ll1,rr1); int M=(L+R)>>1; if(rr<=M) return query(a[t].L,L,M,ll,rr,ll1,rr1); if(ll>M) return query(a[t].R,M+1,R,ll,rr,ll1,rr1); int ans1=query(a[t].L,L,M,ll,M,ll1,rr1); int ans2=query(a[t].R,M+1,R,M+1,rr,ll1,rr1); return max(ans1,ans2); } int main() { //FFF; n=getInt(); m=getInt(); int i; for(i=1;i<=n;i++) b[i].val=getInt(),b[i].id=i,last[i]=0,next[i]=n+1; for(i=1;i<=n;i++) { b[i].last=last[b[i].val]; last[b[i].val]=i; } for(i=n;i>=1;i--) { b[i].next=next[b[i].val]; next[b[i].val]=i; } sort(b+1,b+n+1,cmp); int j=1; for(i=0;i<n;i++) { if(i) root[i]=root[i-1]; while(j<=n&&b[j].last==i) { insert(root[i],0,n+1,b[j].next,b[j].id,b[j].val); j++; } } int ans=0; while(m--) { int L=getInt(); int R=getInt(); L=(L+ans)%n+1; R=(R+ans)%n+1; if(L>R) swap(L,R); ans=query(root[L-1],0,n+1,R+1,n+1,L,R); printf("%d\n",ans); } }