题目大意:要求l,r内不同数的个数,对于相同的数最左边的有效,然后求这些数的下标所组成序列的中位数。
解题思路:题目要求最左边有效,倒着插入即可。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define N 200005
int T[N],ls[N*40],rs[N*40];
int a[N],vis[N],sum[N*40];
int tot;
inline void build(int &now,int l,int r)
{
now=++tot;
sum[now]=0;
if(l==r)return ;
int m=(l+r)>>1;
build(ls[now],l,m);
build(rs[now],m+1,r);
}
inline void update(int &now,int pre,int l,int r,int pos,int val)
{
now=++tot;
sum[now]=sum[pre]+val;
ls[now]=ls[pre],rs[now]=rs[pre];
if(l==r)return ;
int m=(l+r)>>1;
if(pos<=m) update(ls[now],ls[pre],l,m,pos,val);
else update(rs[now],rs[pre],m+1,r,pos,val);
}
inline int query(int rt,int l,int r,int pos)
{
if(r<=pos) return sum[rt];
int m=(l+r)>>1;
if(pos<=m) return query(ls[rt],l,m,pos);
else return query(ls[rt],l,m,pos)+query(rs[rt],m+1,r,pos);
}
inline int Query(int rt,int l,int r,int k)
{
if(l==r)return l;
int m=(l+r)>>1;
int res=sum[ls[rt]];
if(res<k)return Query(rs[rt],m+1,r,k-res);
else return Query(ls[rt],l,m,k);
}
inline int add(int x,int y,int n)
{
return (x+y)>=n?x+y-n:x+y;
}
void init()
{
tot=0;
memset(vis,0,sizeof(vis));
}
int main()
{
int t;
sca(t);
int cas=1;
while(t--){
int n,m;
sca(n),sca(m);
rep(i,1,n)sca(a[i]);
init();
build(T[n+1],1,n);
for(int i=n;i>=1;i--)
{
update(T[i],T[i+1],1,n,i,1);
if(vis[a[i]]) update(T[i],T[i],1,n,vis[a[i]],-1);
vis[a[i]]=i;
}
int pre=0;
int l,r;
printf("Case #%d:",cas++);
for(int i=1;i<=m;i++)
{
sca(l),sca(r);
l=add(l,pre,n)+1;
r=add(r,pre,n)+1;
if(l>r)swap(l,r);
int k=query(T[l],1,n,r);
pre=Query(T[l],1,n,(k+1)/2);
printf(" %d",pre);
}
printf("\n");
}
}