从后向前建主席树,以位置为下标建树,然后查询区间出现次数的第k/2大即可。
复杂度O(nlogn)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e5+10; 4 int num,ans[N],T,pre[N],rt[N],a[N]; 5 struct node 6 { 7 int s,l,r; 8 }t[N*36]; 9 void init() 10 { 11 memset(rt,0,sizeof(rt));num=0; 12 memset(pre,0,sizeof(pre)); 13 } 14 void change(int &x,int y,int l,int r,int p,int w) 15 { 16 x=++num;t[x]=t[y]; 17 if(l==r){t[x].s+=w;return;} 18 int m=l+r>>1; 19 if(m<p)change(t[x].r,t[y].r,m+1,r,p,w); 20 else change(t[x].l,t[y].l,l,m,p,w); 21 t[x].s=t[t[x].l].s+t[t[x].r].s; 22 } 23 int query(int x,int l,int r,int L,int R) 24 { 25 if(l==L&&r==R)return t[x].s; 26 int m=l+r>>1; 27 if(L>m)return query(t[x].r,m+1,r,L,R); 28 else if(m>=R)return query(t[x].l,l,m,L,R); 29 else return query(t[x].l,l,m,L,m)+query(t[x].r,m+1,r,m+1,R); 30 } 31 int find(int x,int l,int r,int p) 32 { 33 if(l==r)return l; 34 int m=l+r>>1; 35 if(t[t[x].l].s>=p)return find(t[x].l,l,m,p); 36 return find(t[x].r,m+1,r,p-t[t[x].l].s); 37 } 38 int main() 39 { 40 scanf("%d",&T);int n,m,cnt; 41 for(int ii=1;ii<=T;++ii) 42 { 43 scanf("%d%d",&n,&m); 44 init(); 45 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 46 for(int i=n;i;--i) 47 { 48 change(rt[i],rt[i+1],1,n,i,1); 49 if(pre[a[i]])change(rt[i],rt[i],1,n,pre[a[i]],-1); 50 pre[a[i]]=i; 51 }ans[0]=0; 52 for(int i=1;i<=m;++i) 53 { 54 int x,y; 55 scanf("%d%d",&x,&y); 56 x=(x+ans[i-1])%n+1; 57 y=(y+ans[i-1])%n+1; 58 if(x>y)swap(x,y); 59 int k=query(rt[x],1,n,x,y); 60 ans[i]=find(rt[x],1,n,(k+1)/2); 61 } 62 printf("Case #%d:",ii); 63 for(int i=1;i<=m;++i)printf(" %d",ans[i]); 64 puts(""); 65 } 66 return 0; 67 }