http://acm.hdu.edu.cn/showproblem.php?pid=5919
题意 求给定一个区间 内有k个不同的数 把它们第一次出现的位置升序排序 问第(k+1)/2个数的下标
首先要找出区间内多少不同数 并且没有修改 用静态主席树维护
主席树查询区间不同数一般就是两种方法
法一https://blog.csdn.net/sunyutian1998/article/details/79825659
法二https://blog.csdn.net/sunyutian1998/article/details/81257416
这里用的法一 从前向后扫一边 每个数都更新到最新出现的位置上 也就是这个数目前出现过的下标中最大的一个 体现再对应版本的线段树上就是该下标处值为1 要找第k大的话直接在这个版本的线段树上二分就可以了
注意数组起码要开40倍
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l;
int r;
int val;
};
node tree[8000010];
int ary[400010],root[400010],ans[400010],mp[400010];
int n,q,len,num;
int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}
int update(int rot,int tar,int val,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val+=val;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
return cur;
}
int queryI(int rot,int pl,int pr,int l,int r)
{
int res,m;
if(pl<=l&&r<=pr) return tree[rot].val;
res=0,m=(l+r)/2;
if(pl<=m) res+=queryI(tree[rot].l,pl,pr,l,m);
if(pr>m) res+=queryI(tree[rot].r,pl,pr,m+1,r);
return res;
}
int queryII(int rot,int val,int l,int r)
{
int m;
if(l==r) return l;
m=(l+r)/2;
if(val<=tree[tree[rot].l].val) return queryII(tree[rot].l,val,l,m);
else return queryII(tree[rot].r,val-tree[tree[rot].l].val,m+1,r);
}
int solve(int rot,int l,int r,int k)
{
int res;
if(l>1) res=queryI(rot,1,l-1,1,n);
else res=0;
res=queryII(rot,k+res,1,n);
return res;
}
int main()
{
int t,cas,i,l,r,k;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++) scanf("%d",&ary[i]);
num=0;
root[n+1]=build(1,n);
memset(mp,0,sizeof(mp));
for(i=n;i>=1;i--)
{
if(mp[ary[i]]!=0)
{
root[i]=update(root[i+1],mp[ary[i]],-1,1,n);
root[i]=update(root[i],i,1,1,n);
}
else
{
root[i]=update(root[i+1],i,1,1,n);
}
mp[ary[i]]=i;
}
for(i=1;i<=q;i++)
{
scanf("%d%d",&l,&r);
l=(l+ans[i-1])%n+1;
r=(r+ans[i-1])%n+1;
if(l>r) swap(l,r);
k=queryI(root[l],l,r,1,n);
k=(k+1)/2;
ans[i]=solve(root[l],l,r,k);
}
printf("Case #%d:",cas);
for(i=1;i<=q;i++) printf(" %d",ans[i]);
printf("\n");
}
return 0;
}