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; }


posted @ 2021-06-02 10:01  xiaodangao  阅读(66)  评论(0编辑  收藏  举报