POI2014 Couriers

Couriers

POI2014
一眼题,但是被卡内存了

题意

求在[l,r]中出现的次数大于(r-l+1)/2 的数

1.一个区间中只会有一个数,因为他出现的次数大于区间的一半

2.如果存在,那么区间第(r-l+1)/2+1大的值,那么答案必然是他

3.只要确认区间第(r-l+1)/2+1大的值的个数是否>(r-l+1)/2即可

4.经典模型:主席树求区间第K值

5.但是此题比较卡内存,如果你有build函数,并且过不了的话,你只要删掉这个函数(不调用),然后恭喜你AC了

具体代码

#include<cstdio>
const int M=500005,N=10600000;
int n,m;
int root[M],sum[N],Ls[N],Rs[N],tot;
void update(int &rt,int pt,int x,int L,int R) {
    rt=++tot;
    sum[rt]=sum[pt]+1;
    Ls[rt]=Ls[pt],Rs[rt]=Rs[pt];
    if(L==R)return;
    int mid=L+R>>1;
    if(x<=mid)update(Ls[rt],Ls[pt],x,L,mid);
    else update(Rs[rt],Rs[pt],x,mid+1,R);
}
int query(int rt,int pt,int lim,int K,int L,int R){
    if(L==R){
        if(sum[rt]-sum[pt]>=lim)return L;
        else return 0;
    }
    int mid=L+R>>1;
    if(sum[Ls[rt]]-sum[Ls[pt]]>=K)return query(Ls[rt],Ls[pt],lim,K,L,mid);
    else return query(Rs[rt],Rs[pt],lim,K-sum[Ls[rt]]+sum[Ls[pt]],mid+1,R);
}
int main() {
    int x;
    scanf("%d %d",&n,&m);
    for(int i=1; i<=n; i++) {
        scanf("%d",&x);
        update(root[i],root[i-1],x,1,n);
    }
    int l,r;
    for(int i=1; i<=m; i++) {
        scanf("%d %d",&l,&r);
        printf("%d\n",query(root[r],root[l-1],(r-l+1)/2+1,(r-l+1)/2+1,1,n));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值