题目:
n个数m个询问,每个询问是一个[l,r],输出[l,r]之前的众数。有相同的输出小的。n <=40000,m<=50000,ai<=1e9
分析:
分块。
预处理出f[i][j]表示第i个块到第j个块的众数。对于一个询问[l,r],中间整块的部分可以直接得到答案ans,然后对于两边的2*sqrt(n)个元素,查询出每个元素的出现次数,看是否能更新ans。至于,查找一个[l,r]内x的出现次数,可通过记录x的每个出现位置,二分上下界得到。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 4e4 + 5;
const double EPS = 1e-8;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
map<int, int> mp;
int v[MAXN], val[MAXN], id, cnt[MAXN], bl[MAXN],f[905][905],blo,n,m;
int first[MAXN],last[MAXN];
struct data{int v,p;}b[MAXN];
bool operator <(data a, data b) {
return a.v < b.v || (a.v == b.v && a.p < b.p);
}
void pre(int x) {
for(int i=1;i<=id;i++) cnt[i] = 0;
int mx = 0, ans = 0;
for (int i = (x - 1) * blo + 1; i <= n; i++) {
cnt[v[i]]++;
int t = bl[i];
if (cnt[v[i]] > mx || (cnt[v[i]] == mx && val[v[i]] < val[ans])) {
mx = cnt[v[i]];
ans = v[i];
}
f[x][t] = ans;
}
}
int findup(int x,int v){
int l = first[v], r = last[v];
int tmp = 0;
while(l<=r){
int mid = (l+r)>>1;
if(x < b[mid].p) r = mid - 1;
else {l=mid+1;tmp=mid;}
}
return tmp;
}
int finddown(int x,int v){
int l = first[v], r = last[v];
int tmp = INF;
while(l<=r){
int mid = (l+r)>>1;
if(x>b[mid].p) l=mid+1;
else{r=mid-1;tmp=mid;}
}
return tmp;
}
int find(int x,int y,int v){
return max(0,findup(y,v)-finddown(x,v)+1);
}
int query(int a, int b) {
int ans, mx;
ans = f[bl[a] + 1][bl[b] - 1];
mx = find(a, b, ans);
for (int i = a; i <= min(bl[a]*blo, b); i++) {
int t = find(a,b,v[i]);
if(mx < t || (mx == t && val[v[i]] < val[ans])){
ans = v[i];
mx = t;
}
}
if(bl[a] != bl[b]){
for(int i=(bl[b]-1)*blo+1;i<=b;i++){
int t = find(a,b,v[i]);
if(mx < t || (mx == t && val[v[i]] < val[ans])){
ans = v[i];
mx = t;
}
}
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
n = read(); m = read();
blo = sqrt((double)n / log((double)n) * log(2));
for (int i = 1; i <= n; i++) {
bl[i] = (i - 1) / blo + 1;
v[i] = read();
if (!mp.count(v[i])) {
mp[v[i]] = ++id;
val[id] = v[i];
}
v[i] = mp[v[i]];
b[i].p = i, b[i].v = v[i];
}
sort(b + 1, b + n + 1);
for (int i = 1; i <= n; i++) {
if (!first[b[i].v]) first[b[i].v] = i;
last[b[i].v] = i;
}
for (int i = 1; i <= bl[n]; i++) pre(i);
int ans = 0;
while(m--) {
int a, b;
a = read(); b = read();
a = (a + ans - 1) % n + 1, b = (b + ans - 1) % n + 1;
if (a > b) swap(a, b);
ans = val[query(a, b)];
printf("%d\n",ans);
}
return 0;
}