LibreOJ #2432. 「POI2014」代理商 Couriers【主席树】

2432. 「POI2014」代理商 Couriers

【题目描述】
传送门

【题解】

主席树套一下就可以了,这个值肯定在左子树或右子树中,所以挑一个大的递归,如果大的这棵子树还是小于一半,那么输出0。

代码如下

#include<cstdio>
#include<cctype>
#define MAXN 500005
using namespace std;
int n,m,T[MAXN],HALF;
int cnt,Tre[MAXN*20],L[MAXN*20],R[MAXN*20];
int read(){
    int ret=0;char ch=getchar();bool f=1;
    for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
    for(; isdigit(ch);ch=getchar()) ret=(ret<<3)+(ret<<1)+ch-48;
    return f?ret:-ret;
}
int Updata(int lst,int l,int r,int p){
    int rt=++cnt;
    Tre[rt]=Tre[lst]+1;L[rt]=L[lst];R[rt]=R[lst];
    if(l<r){
        int mid=(r+l)>>1;
        if(p<=mid) L[rt]=Updata(L[lst],l,mid,p);
        else R[rt]=Updata(R[lst],mid+1,r,p);
    }
    return rt;
}
int Query(int u,int v,int l,int r){
    if(l>=r) return l;
    int mid=(r+l)>>1,NowL=Tre[L[v]]-Tre[L[u]],NowR=Tre[R[v]]-Tre[R[u]];
    if(NowL>HALF) return Query(L[u],L[v],l,mid);else
    if(NowR>HALF) return Query(R[u],R[v],mid+1,r);else return 0;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("2432.in","r",stdin);
    freopen("2432.out","w",stdout);
    #endif
    n=read(),m=read();
    for(int i=1;i<=n;i++) T[i]=Updata(T[i-1],1,n,read());
    for(int i=1;i<=m;i++){
        int l=read(),r=read();HALF=(r-l+1)>>1;
        printf("%d\n",Query(T[l-1],T[r],1,n));
    }
    return 0;
}
posted @ 2018-07-03 18:55  XSamsara  阅读(83)  评论(0编辑  收藏  举报