题目很恶心,题意不解释了。
正解主席树,但是听说分块能过这题就试着就分块搞一搞。。最后将块大小改大后莽过去了。。(交了无数发差点号都没了)
思路:
基本分块后,预处理每个位置的数前一个出现的位置,因为要求中位数,那么事先对每个块进行sort排序下。处理这些的复杂度就是 n ∗ 块 数 n*块数 n∗块数
接下去查询的时候,先处理一下每个块内有多少数字有效,有效数字就是当前位置的数字上次出现的位置不在查询的区间内。
然后就是一个分块的模拟了,,看代码应该能理解。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 2e5+5;
const int mod = 1e9+7;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,q,a[maxn],l[maxn],r[maxn],num,belong[maxn];
int last[maxn],tmp[maxn],pos[maxn],dif[maxn];
void build(){
int block = 3*sqrt(n);
num = n/block;
if(n%block) num++;
for(int i = 1; i <= num; i++){
l[i] = (i-1)*block+1;
r[i] = i*block;
}
r[num] = n;
for(int i = 1; i <= n; i++)
belong[i] = (i-1)/block+1;
for(int i = 1; i <= n; i++){
pos[i] = last[a[i]];
tmp[i] = pos[i];
last[a[i]] = i;
}
for(int i = 1; i <= num; i++){
sort(pos+l[i],pos+r[i]+1);
}
}
int query(int x,int y){
int cnt = 0;
if(belong[x] == belong[y]){
for(int i = x; i <= y; i++){
if(tmp[i] < x) cnt++;
}
int mid = (cnt+1)/2;
cnt = 0;
for(int i = x; i <= y; i++){
if(tmp[i] < x) cnt++;
if(cnt == mid) return i;
}
}
for(int i = x; i <= r[belong[x]]; i++)
if(tmp[i] < x) cnt++;
for(int i = belong[x]+1; i < belong[y]; i++){
dif[i] = lower_bound(pos+l[i],pos+r[i]+1,x)-pos-l[i]; //二分当前块内第一个大于边界的数的下标,那么块内这个下标之前的数都是有效的数
cnt += dif[i];
}
for(int i = l[belong[y]]; i <= y; i++)
if(tmp[i] < x) cnt++;
int mid = (cnt+1)/2;
cnt = 0;
for(int i = x; i <= r[belong[x]]; i++){
if(tmp[i] < x) cnt++;
if(cnt == mid) return i;
}
for(int i = belong[x]+1; i < belong[y]; i++){
int res = cnt;
cnt += dif[i];
if(cnt >= mid){
for(int j = l[i]; j <= r[i]; j++){
if(tmp[j] < x) res++;
if(res == mid) return j;
}
}
}
for(int i = l[belong[y]]; i <= y; i++){
if(tmp[i] < x) cnt++;
if(cnt == mid) return i;
}
}
void init(){
mem(last,0);
}
int ans[maxn];
int main() {
int t;
scanf("%d",&t);
int ca = 0;
while(t--){
init();
int res = 0;
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
build();
int x,y;
for(int i = 1; i <= q; i++){
scanf("%d%d",&x,&y);
x = (x+res)%n+1;
y = (y+res)%n+1;
if(x > y) swap(x,y);
res = query(x,y);
ans[i] = res;
}
printf("Case #%d:",++ca);
for(int i = 1; i <= q; i++)
printf(" %d",ans[i]);
printf("\n");
}
}