D. Cut and Stick(Codeforces Round #716 (Div. 2)题解)
题目链接:D. Cut and Stick
思路:询问最少需要分成几个区间,如果该区间众数小于等于\(\lceil \frac{len}{2} \rceil\),那么显然答案是1。否则的话,我们需要尽可能的满足众数的要求,将尽可能多的众数放在一个区间里面,所以一个区间里面最多能够放的个数是其他数的个数+1,其余的众数就分成长度为1的区间。需要注意的是,如果我们得到的众数答案小于等于\(\lceil \frac{len}{2} \rceil\),那么有可能我们取得的不是真正的众数,但也无伤大雅。具体做法就是利用主席树进行维护。
\(Code:\)
/* -*- encoding: utf-8 -*-
'''
@File : 255.cpp
@Time : 2021/05/31 21:05:02
@Author : puddle_jumper
@Version : 1.0
@Contact : 1194446133@qq.com
'''
# here put the import lib*/
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb emplace_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
static char c;
static int f;
for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
x*=f;
}
template<typename T>void write(T x){
static char q[65];
int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}
const int N = 3e5+10;
int n,q;
int root[N];
int a[N];
int idx ;
struct node{
int l,r,cnt;
}tr[N*20];
int add(int l,int r,int p,int k){
int mid = l + r >> 1;
int q = ++idx;
tr[q] = tr[p];
if(l == r){tr[q].cnt++;return q; }
if(k<=mid)tr[q].l = add(l,mid,tr[p].l,k);
else tr[q].r = add(mid+1,r,tr[p].r,k);
tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
return q;
}
int query(int l,int r,int p,int q){
int mid = l + r >> 1;
if(l == r) {return tr[q].cnt - tr[p].cnt; }
int cnt1 = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int cnt2 = tr[tr[q].r].cnt - tr[tr[p].r].cnt;
if(cnt1 > cnt2)return query(l,mid,tr[p].l,tr[q].l);
else if(cnt1<cnt2)return query(mid+1,r,tr[p].r,tr[q].r);
else return 0;
}
void solve(){
read(n);read(q);
rep(i,1,n)read(a[i]),root[i] = add(1,n,root[i-1],a[i]);
while(q--){
int u,v;
read(u);read(v);
int sum = query(1,n,root[u-1],root[v]);
int lens = v - u + 1;
int mx = ceil(lens/2.0);
if(sum <= mx){
pc('1');
}
else {
int k = lens - sum;
k++;
write(sum-k+1);
}
pc('\n');
}
}
signed main(){solve(); return 0; }