P3567 [POI2014]KUR-Couriers

余生长醉 提交于 2019-12-04 09:10:59

简单的主席树上二分。。。
出现次数超过区间长度一半的数肯定在左右子树中sz更大的那个中
向sz更大的子树上跳,如果节点总数就小于区间长度的一半则无解
因为没说ai取值范围所以离散化一下

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int root[500500];
struct Node{
    int lson,rson,sz;
}Seg[500500*30];
int n,m,Nodecnt=0;
void insert(int l,int r,int &o,int v){
    int p=++Nodecnt;
    Seg[p]=Seg[o];
    Seg[p].sz++;
    o=p;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    if(v<=mid)
        insert(l,mid,Seg[o].lson,v);
    else
        insert(mid+1,r,Seg[o].rson,v);
}
int solve(int L,int R,int l,int r,int lo,int ro){
    if(Seg[ro].sz-Seg[lo].sz<=((R-L+1)>>1))
        return -1;
    if(l==r&&(Seg[ro].sz-Seg[lo].sz)>((R-L+1)>>1))
        return l;
    int mid=(l+r)>>1;
    if(Seg[Seg[ro].rson].sz-Seg[Seg[lo].rson].sz>Seg[Seg[ro].lson].sz-Seg[Seg[lo].lson].sz)
        return solve(L,R,mid+1,r,Seg[lo].rson,Seg[ro].rson);
    else
        return solve(L,R,l,mid,Seg[lo].lson,Seg[ro].lson);
}
int a[500500],b[500500],len;
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    len=unique(b+1,b+n+1)-(b+1);
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+len+1,a[i])-b;
    }
    for(int i=1;i<=n;i++){
        root[i]=root[i-1];
        insert(1,len,root[i],a[i]);
    } 
    for(int i=1;i<=m;i++){
        int l,r;
        scanf("%d %d",&l,&r);
        int rev=solve(l,r,1,len,root[l-1],root[r]);
        if(rev==-1){
            printf("%d\n",0);
        }
        else{
            printf("%d\n",b[rev]);
        }
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!