P4168
P4168
题意简述
给定一个长度为 $ n $ 的序列 \(a_i\)
强制在线 区间求众数
如果有多个众数,求其中最小的
\(m\) 次询问
\(1≤n≤40000\),$ 1≤m≤50000 $,\(1≤a_i≤10^9\)
Solution
首先值域与 $ n $ 的大小相差极大
离散化是必然的
已知区间 \([x,y]\) 的众数与区间 \([y+1,z]\) 的众数难以推出 \([x,z]\) 的众数,因此不好使用线段树或树状数组等维护
分块连接大脑,卡常代替思考
容易想到分块,预处理出以每一个块的右边界为右端点的前缀的桶.
for(int i = 1;i<=cntb;i++){
memcpy(cnt[i],cnt[i-1],sizeof(cnt[i]));//继承上一个桶
for(int j = L[i];j<=R[i];j++){//本块内出现的数
cnt[i][a[j]]++;//维护以本块右边界为右端点的前缀的桶
}
}
for(int i = 1;i<=cntb;i++){
for(int j = i;j<=cntb;j++){
//md即为众数
//新的区间的众数只有可能是上一个区间的众数或新块内的数
md[i][j] = md[i][j-1];//继承上一个众数区间
for(int k = L[j];k<=R[j];k++){//新的块
int t1 = a[k];
int t2 = md[i][j];
if((cnt[j][t1]-cnt[i-1][t1]>cnt[j][t2]-cnt[i-1][t2])||((cnt[j][t1]-cnt[i-1][t1]==cnt[j][t2]-cnt[i-1][t2]) && (t1<t2))){
md[i][j] = t1;//计算众数
}
}
}
}
对于每一次询问,答案显然只有可能是连续整块的众数或是散块内出现的数
整块直接查询.散块暴力即可.
分析复杂度:
设块长为 \(B\) ,则块数为 \(\frac{n}{B}\) ,预处理 \(O(\frac{n}{B}*\frac{n}{B} * B) = O(\frac{n^2}{B})\)
单次询问 \(O(B)\), \(m\) 次即为 \(O(mB)\)
总复杂度 \(O(\frac{n^2}{B}+mB)\)
为平衡这两项,\(B\) 应取 \(\frac{n}{\sqrt{m}}\)
此时复杂度 \(O(n \sqrt{m})\)
足以通过此题
Code
#include <bits/stdc++.h>
#define rg register
#define il inline
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using namespace std;
namespace myspace{
const char endl = '\n';
const int maxn = 4e4+50;
const int B = 512;
const int maxb = maxn/B+50;
int b[maxn],a[maxn];
int cnt[maxb][maxn];
int tmp[maxb][maxn];
int md[maxb][maxb];
int n,m;
int cntb;
int bel[maxn];
int L[maxn],R[maxn];
void init(){
cntb = (n-1)/B+1;
for(int i = 1;i<=n;i++){
bel[i] = (i-1)/B+1;
}
for(int i = 1;i<=cntb;i++){
L[i] = B*(i-1)+1;
R[i] = min(B*i,n);
}
for(int i = 1;i<=cntb;i++){
memcpy(cnt[i],cnt[i-1],sizeof(cnt[i]));
memcpy(tmp[i],tmp[i-1],sizeof(tmp[i]));
for(int j = L[i];j<=R[i];j++){
cnt[i][a[j]]++;
tmp[i][a[j]]++;
}
}
for(int i = 1;i<=cntb;i++){
for(int j = i;j<=cntb;j++){
md[i][j] = md[i][j-1];
for(int k = L[j];k<=R[j];k++){
int t1 = a[k];
int t2 = md[i][j];
if((cnt[j][t1]-cnt[i-1][t1]>cnt[j][t2]-cnt[i-1][t2])||((cnt[j][t1]-cnt[i-1][t1]==cnt[j][t2]-cnt[i-1][t2]) && (t1<t2))){
md[i][j] = t1;
}
}
}
}
}
il int qry(int l,int r){
if(l>r){
swap(l,r);
}
int bl = bel[l];
int br = bel[r];
int ans = md[bl+1][br-1];
if(br-bl<=1){
for(int i = l;i<=r;i++){
cnt[0][a[i]]++;
if(cnt[0][a[i]]>cnt[0][ans] || (cnt[0][a[i]] == cnt[0][ans] && a[i]<ans)){
ans = a[i];
}
}
for(int i = l;i<=r;i++){
cnt[0][a[i]]--;
}
return ans;
}
for(int i = l;i<=R[bl];i++){
cnt[br-1][a[i]]++;
if((cnt[br-1][a[i]]-tmp[bl][a[i]]>cnt[br-1][ans]-tmp[bl][ans]) || (((cnt[br-1][a[i]]-tmp[bl][a[i]]==cnt[br-1][ans]-tmp[bl][ans])) && (a[i]<ans))){
ans = a[i];
}
}
for(int i = L[br];i<=r;i++){
cnt[br-1][a[i]]++;
if((cnt[br-1][a[i]]-tmp[bl][a[i]]>cnt[br-1][ans]-tmp[bl][ans]) || (((cnt[br-1][a[i]]-tmp[bl][a[i]]==cnt[br-1][ans]-tmp[bl][ans])) && (a[i]<ans))){
ans = a[i];
}
}
for(int i = l;i<=R[bl];i++){
cnt[br-1][a[i]]--;
}
for(int i = L[br];i<=r;i++){
cnt[br-1][a[i]]--;
}
return ans;
}
int x;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> m;
for(int i = 1;i<=n;i++){
cin >> b[i];
a[i] = b[i];
}
sort(b+1,b+1+n);
int tn = unique(b+1,b+1+n)-b-1;
for(int i = 1;i<=n;i++){
a[i] = lower_bound(b+1,b+1+tn,a[i])-b;
}
init();
for(int i = 1;i<=m;i++){
int l,r;
cin >> l >> r;
l = (l+x-1)%n+1;
r = (r+x-1)%n+1;
x = b[qry(l,r)];
cout << x << endl;
}
return 0;
}
}
signed main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
myspace::main();
return 0;
}

浙公网安备 33010602011771号