Codeforces Round #716 (Div. 2) D
题意:区间查询,问区间最少能分成几部分使得最多的数不超过总数的一半 向上取整。
思路:找到区间的总数s,如果不超过一半的话就是一部分。超过一半的话,那我们只要考虑超过一半的那一个数怎么组合,超过一半的数为f,那f和其他一个数组合,剩下的f就单独,用贪心的思想可以看出这是最优的,那么答案就是 2*ans-(r-l+1);那我们怎么求众数呢,可以用莫队,分块,线段树,这里还可以用随机算法,因为f是超过一半的,那我们随机 k次 ,可以随机不到f的概率是 (1/2)^k ,当k等于 40 50 的时候 这个概率是几乎不可能的。
#include<bits/stdc++.h>
using namespace std;
int n,q,l,r,a[300005];
vector<int> v[300005];
#define all(v) (v).begin(),(v).end()
int main() {srand(time(NULL));scanf("%d%d",&n,&q);for(int i=1;i<=n;i++) {scanf("%d",a+i);v[a[i]].push_back(i);}for(int i=1;i<=q;i++) {scanf("%d%d",&l,&r);int ans=0;for(int j=1;j<=40;j++) {int id=a[rand()*rand()%(r-l+1)+l];ans=max(ans,int(upper_bound(all(v[id]),r)-lower_bound(all(v[id]),l)));}cout<<max(1,ans+ans-(r-l+1))<<endl;}return 0;
}