P3567-Couriers-(出现的次数大于区间个数的一半==静态第K小主席树模板)

题目
Waterfall
在这里插入图片描述
假如一个数在区间出现的次数大于一半,第(r-l+3)/2小的一定是这个数,然后只要检测这个数出现的次数是否>一半即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e5+5;
struct tree{int l,r,sum;}t[N*100];
int refl[N],a[N],tot;
int root[N],sz,ans;
void update(int l,int r,int &x,int y,int n)
{
    t[++sz]=t[y],t[sz].sum++,x=sz;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    if(n<=mid)
        update(l,mid,t[x].l,t[y].l,n);
    else
        update(mid+1,r,t[x].r,t[y].r,n);
}
int query(int l,int r,int x,int y,int k)
{
    if(l==r)
    {
        ans=t[y].sum-t[x].sum;//第k小这个数在询问区间内出现的次数 看其是否>=(r-l+1);
        return l;
    }
    int mid=(l+r)>>1;
    int left=t[t[y].l].sum-t[t[x].l].sum;
    if(k<=left)
        return query(l,mid,t[x].l,t[y].l,k);
    return query(mid+1,r,t[x].r,t[y].r,k-left);
}
int main()
{
    sz=0;
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),refl[i]=a[i];
    sort(refl+1,refl+n+1);
    tot=unique(refl+1,refl+n+1)-(refl+1);
    for(int i=1;i<=n;i++)
    {
        int dex=lower_bound(refl+1,refl+tot+1,a[i])-refl;
        update(1,tot,root[i],root[i-1],dex);
    }
    while(m--)
    {
        int l,r;scanf("%d%d",&l,&r);
        int fin=refl[query(1,tot,root[l-1],root[r],(r-l+3)/2)];
        if(ans<=(r-l+1)/2)
            printf("0\n");
        else
            printf("%d\n",fin);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/89969806