版权声明:本文为博主原创文章,未经博主允许也可以转载。 https://blog.csdn.net/FrankAx/article/details/82941156
分块算法求众数的主要思路就是,先预处理出任意整个块之间的众数,然后查询的时候O(1)的到L,R区间内整块的众数,然后再暴力枚举左右多余的数中是否有超过整个块中的众数。
P4168
开氧气才能过。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
map<int,int>mp;
const int AX = 5e4 + 666 ;
int tot ;
int v[AX];
int val[AX];
int block[AX];
std::vector<int> vec[AX];
int len ;
int cnt[AX];
int f[606][606];
int n , m ;
LL read(){
LL 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;
}
void update( int x ){
memset( cnt , 0 , sizeof(cnt) ) ;
int mx = 0 , idx = 0 ;
for( int i = (x-1)*len+1 ; i <= n ; i++ ){
cnt[v[i]] ++ ;
if( mx < cnt[v[i]] || ( mx == cnt[v[i]] && val[v[i]] < val[idx] ) ){
mx = cnt[v[i]] ; idx = v[i] ;
}
f[x][block[i]] = idx ;
}
}
inline int get_num( int l ,int r ,int x){
return upper_bound( vec[x].begin() , vec[x].end() , r ) - lower_bound( vec[x].begin() , vec[x].end() , l ) ;
}
inline int query( int l , int r ){
int idx = f[block[l]+1][block[r]-1];
int mx = get_num( l , r , idx ) ;
for( int i = l ; i <= min( r , block[l] * len ) ; i++ ){
int t = get_num( l , r , v[i] ) ; //得到l,r区间内v[i](众数)的个数
if( t > mx || ( t == mx && val[v[i]] < val[idx] ) ){
mx = t ; idx = v[i] ;
}
}
if( block[l] != block[r] ){
for( int i = ( block[r] - 1 ) * len + 1 ; i <= r ; i++ ){
int t = get_num( l , r , v[i] ) ;
if( t > mx || ( t == mx && val[v[i]] < val[idx] ) ){
mx = t ; idx = v[i] ;
}
}
}
return idx ;
}
int main(){
//scanf("%d%d",&n,&m);
n = read();
m = read();
len = 200 ;
for( int i = 1 ; i <= n ; i++ ){
//scanf("%d",&v[i]);
v[i] = read();
if( !mp[v[i]] ){
mp[v[i]] = ++tot;
val[tot] = v[i] ;
}
v[i] = mp[v[i]];
vec[v[i]].push_back(i) ;
}
for( int i = 1 ; i <= n ; i++ ) block[i] = ( i - 1 ) / len + 1 ;
for( int i = 1 ; i <= block[n] ; i++ ){
update(i) ;
}
int l , r ;
int res = 0 ;
for( int i = 1 ; i <= m ; i++ ){
//scanf("%d%d",&l,&r);
l = read();
r = read();
l = ( l + res - 1 ) % n + 1 ;
r = ( r + res - 1 ) % n + 1 ;
if( l > r ) swap( l , r ) ;
res = val[query(l,r)] ;
printf("%d\n",res);
}
return 0 ;
}