Codeforces Round #716 (Div. 2) D. Cut and Stick(主席树)
题意:
给出一个数组 a a a , q q q 次询问,每次询问求区间 [ l , r ] [l,r] [l,r] 最少要分成多少个子序列,满足每个子序列中最多的数的数量 ≤ \leq ≤ ( l e n g t h + 1 ) / 2 (length+1)/2 (length+1)/2。
题解:
这题看别人是用莫队写的,但我很久之前学过,现在忘了,所以只能介绍主席树怎么写。
这题就是求区间众数的个数。分两种情况。
1. 1. 1.数量 ≤ ( r − l + 2 ) / 2 \leq (r-l+2)/2 ≤(r−l+2)/2, 那么肯定分为 1 1 1个就行。
2. 2. 2.数量 > ( r − l + 2 ) / 2 >(r-l+2)/2 >(r−l+2)/2 ,那么就看剩下还剩多少数,看这些数最多能和多少个众数一起,那么剩下的众数就单独一个。
怎么求区间众数呢,用主席树维护 ( 1 , n ) (1,n) (1,n) 每个数出现多少次,在查询的时候如果左节点的个数 > ( r − l + 2 ) / 2 >(r-l+2)/2 >(r−l+2)/2 ,说明众数一定在左区间,否则在右区间。
代码:
#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=3e5+5;
const int inf=0x3f3f3f3f;
int a[MAXN];
int tree[MAXN];
int cnt=0;
struct node
{
    int l,r;
    int sum;
}node[MAXN*40];
void insert(int l,int r,int pre,int& now,int val)
{
    now=++cnt;
    node[now]=node[pre];
    node[now].sum++;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    if(val<=mid)
    {
        insert(l,mid,node[pre].l,node[now].l,val);
    }
    else insert(mid+1,r,node[pre].r,node[now].r,val);
}
int query(int l,int r,int pre,int now,int k)
{
    if(l==r)
    {
        return node[now].sum-node[pre].sum;
    }
    int mid=(l+r)>>1;
    int cnt=node[node[now].l].sum-node[node[pre].l].sum;
    if(cnt>k)
    {
        return query(l,mid,node[pre].l,node[now].l,k);
    }
    else return  query(mid+1,r,node[pre].r,node[now].r,k);
}
int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        insert(1,n,tree[i-1],tree[i],a[i]);
    }
    while(q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        int k=(r-l+2)/2;
        int ans=query(1,n,tree[l-1],tree[r],k);
        //cout<<ans<<endl;
        int len=(r-l+1);
        ans=max(1,ans-(len-ans));
        printf("%d\n",ans);
    }
}

 
                
             
         浙公网安备 33010602011771号
浙公网安备 33010602011771号