题意和链接前面的blog有,就不再提。。
思路:本来实在是莽不过去。。后来想到其实复杂度均摊下来每块取比sqrt(n)大一些更好。。具体大多少。。嗯。。大概x^2/logx=N 。?我也不会解。。。
所以n取了个2*sqrt(n)结果卡过去了。。。重要的还是思想。。分块后每块排序,和3333套路差不多,时间复杂度O(n*sqrt(n)*log(n))复杂度一看就不小。。不过编码很简单暴力。。毕竟数据结构实在写不了也可以莽一下嘛。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200010;
int n,q,block,num;
int a[MAXN];
int belong[MAXN],L[MAXN],R[MAXN],c[MAXN],d[MAXN],mp[MAXN],tmp[MAXN];
int build(int n){
block=sqrt(n)*2;
num=n/block;
if(n%block!=0) num++;
for(int i=0;i<num;i++){
L[i]=i*block+1;
R[i]=(i+1)*block;
}
R[num-1]=n;
int cnt=0;
for(int i=1;i<=n;i++){
if(i<=R[cnt]) belong[i]=cnt;
else belong[i]=++cnt;
}
memset(mp,0,sizeof(mp));
for(int i = 1; i<= n; i++){
c[i]=mp[a[i]];
mp[a[i]] = i;
}
for(int i=1;i<=n;i++) d[i]=c[i];
for(int i=0;i<num;i++){
sort(c+L[i],c+R[i]+1);
}
}
int query(int l,int r){
int ret=0;
if(belong[l]==belong[r]){
for(int i=l;i<=r;i++){
if(d[i]<l) ++ret;
}
int x=(ret+1)/2;
ret=0;
for(int i=l;i<=r;i++){
if(d[i]<l) ++ret;
if(ret==x) return i;
}
}
for(int i=l;i<=R[belong[l]];i++){
if(d[i]<l) ++ret;
}
for(int i=belong[l]+1;i<belong[r];i++){
tmp[i]=(int)(lower_bound(c+L[i],c+R[i]+1,l)-c)-L[i];
ret+=tmp[i];
}
for(int i=L[belong[r]];i<=r;i++){
if(d[i]<l) ++ret;
}
int x=(ret+1)/2;
ret=0;
for(int i=l;i<=R[belong[l]];i++){
if(d[i]<l) ++ret;
if(ret==x) return i;
}
for(int i=belong[l]+1;i<belong[r];i++){
int tm=ret;
ret+=tmp[i];
if(ret>=x){
for(int j=L[i];j<=R[i];j++){
if(d[j]<l) ++tm;
if(tm==x) return j;
}
}
}
for(int i=L[belong[r]];i<=r;i++){
if(d[i]<l) ++ret;
if(ret==x) return i;
}
}
int Q[MAXN];
int main(){
Q[0]=0;
int t,cas=1;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
build(n);
int l,r;
for(int i=1;i<=q;i++){
scanf("%d%d",&l,&r);
l=(l+Q[i-1])%n+1;
r=(r+Q[i-1])%n+1;
if(r<l) swap(l,r);
Q[i]=query(l,r);
}
printf("Case #%d:",cas++);
for(int i=1;i<=q;i++) printf(" %d",Q[i]);
printf("
");
}
return 0;
}