Leetcode1157-子数组中占绝大多数的元素

线段树:

        在线段树的每个结点中,用摩尔投票来维护一个区间中的可能的众数,这里需要重载一下线段树中的+操作,对于每次询问,我们可以在logn的时间内找到可能的众数。

        此外,我们需要用一个s数组来保存每个元素的下标,因为是顺序遍历arr数组,所以每个元素在s数组中保存的下标一定是递增的。

        对于询问query(int l,int r,int threshold),我们先在线段树中找到可能的众数ans,然后在s[ans]上二分查找在[l,r]的区间ans有len个,如果len<threshold,那么说明这个众数不满足要要求,返回-1,否则返回ans。

class MajorityChecker {
struct node{
    int l,r;
    int val,cnt;
    node operator+(const node &p)const{
        node res;
        if(val==p.val){
            res.val=val;
            res.cnt=cnt+p.cnt;
        }else if(cnt>p.cnt){
            res.val=val;
            res.cnt=cnt-p.cnt;
        }else{
            res.val=p.val;
            res.cnt=p.cnt-cnt;
        }
        res.l=min(l,p.l);
        res.r=max(r,p.r);
        return res;
    }
}tr[80010];
int n;
vector<int> a;
vector<int> s[20010];

void build(int u,int l,int r){
    tr[u]={l,r};
    if(l==r){
        tr[u]={l,r,a[l],1};
        return;
    }
    int m=(l+r)>>1;
    build(u<<1,l,m);
    build(u<<1|1,m+1,r);
    tr[u]=tr[u<<1]+tr[u<<1|1];
}

node queryy(int u,int l,int r){
    if(l==tr[u].l&&tr[u].r==r) return tr[u];
    int m=(tr[u].l+tr[u].r)>>1;
    if(r<=m) return queryy(u<<1,l,r);
    if(l>m) return queryy(u<<1|1,l,r);
    return queryy(u<<1,l,m)+queryy(u<<1|1,m+1,r);
}

public:
    MajorityChecker(vector<int>& arr) {
        n=arr.size();
        a.push_back(-1);
        for(int i=0;i<n;i++){
            a.push_back(arr[i]);
            s[arr[i]].push_back(i+1);
        }
        build(1,1,n);
    }
    
    int query(int left, int right, int threshold) {
        int ans=queryy(1,left+1,right+1).val;
        int len=upper_bound(s[ans].begin(),s[ans].end(),right+1)-lower_bound(s[ans].begin(),s[ans].end(),left+1);
        if(len<threshold) return -1;
        return ans;
    }
};

时间复杂度:O((n+q)logn)

空间复杂度:O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值