题意:
给定长度为n的序列a,q次询问,
每次询问给定L,R,你可以将[L,R]中的数放进若干个盒子,
要求满足每盒子中的众数出现次数<=(盒子中数总数+1)/2,
问最少需要多少个盒子。
数据范围:n,q<=3e5,a(i)<=n
解法:
设[l,r]的长度为len,众数个数为cnt,那么非众数个数x=len-cnt.
x个非众数可以和x+1个众数放在一起,满足条件,
多出来的众数只能一个一个放了,个数为cnt-(x+1).
因此需要的总个数为cnt-(len-cnt+1)+1=cnt*2-len.
计算区间众数我用的莫队算法.
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e6+5;
const int block=2000;
struct QQ{
int l,r,id;
}Q[maxm];
int a[maxm];
int res[maxm];
int cnt[maxm];
int cnt2[maxm];
int n,q;
int ans;
bool cmp(QQ a,QQ b){
if(a.l/block!=b.l/block)return a.l<b.l;
return a.r<b.r;
}
void add(int x){
cnt[a[x]]++;
cnt2[cnt[a[x]]]++;
if(cnt2[cnt[a[x]]]==1)ans++;
}
void del(int x){
cnt2[cnt[a[x]]]--;
if(cnt2[cnt[a[x]]]==0)ans--;
cnt[a[x]]--;
}
void solve(){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=q;i++){
int l,r;cin>>l>>r;
Q[i]={l,r,i};
}
sort(Q+1,Q+1+q,cmp);
int l=Q[1].l,r=l-1;
for(int i=1;i<=q;i++){
int ql=Q[i].l,qr=Q[i].r;
while(l>ql)add(--l);
while(r<qr)add(++r);
while(l<ql)del(l++);
while(r>qr)del(r--);
int len=qr-ql+1;
int t=(len+1)/2;
if(ans<=t)res[Q[i].id]=1;
else res[Q[i].id]=ans*2-len;
}
for(int i=1;i<=q;i++){
cout<<res[i]<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
solve();
return 0;
}