前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode 327. Count of Range Sum(线段树)

LeetCode 327. Count of Range Sum(线段树)

作者头像
ShenduCC
发布2020-03-16 23:45:59
1.1K0
发布2020-03-16 23:45:59
举报
文章被收录于专栏:算法修养

题意:找出所有区间和在某个范围之内的个数

题解:区间问题用线段树来做。首先n^2 可以遍历所有的区间,这样会超时。

代码语言:javascript
复制
       我们用线段树,期望可以在遍历整个线段树的过程中把问题解决掉,遍历整个线段树的效率是O(n*logn) 如果遍历每个节点上的区间上所花的时间是n*logn,也可以接受,总的效率就是O(n*logn*logn)

       线段树每个节点,存储这个区间的前缀区间和,和后缀区间和,而且要是排好序的。

       父节点的区间个数,需要计算它的两个子节点中,左子节点的后缀区间和和右子节点的前缀区间和,相加有没有符合条件的。也就是两个排好序的数组,求两个数组里两个数字之和在某个范围的组合的个数。这里可以用n*logn的方法解决。
       同时父亲节点的前缀区间和和后缀区间和,也要由两个子节点得来,使用归并排序,O(n)。

       另外一定要注意,vector 超时,只能用数组了。
代码语言:javascript
复制
typedef long long int _int;

class Solution {
public:
    _int* l[10005*17];
    _int* r[10005*17];
    int sizel[10005*17];
    int sizer[10005*17];
    _int range[10005*17];
    vector<int> num;
    _int low;
    _int upp;
    _int ans;
    int countRangeSum(vector<int>& nums, int lower, int upper) {

        if(nums.size()==0)
            return 0;

        low = lower;
        upp = upper;
        num = nums;
        build(1,0,nums.size()-1);

        return ans;
    }

    int fun(int node,_int* a,int lena,_int* b,int lenb,int y,_int* &c)
    {
        _int x = range[y];
        int i=0,j=0;
        c = new _int[lena+ lenb];
        int pos=0;
        while(i<lena||j<lenb)
        {
            if(i>=lena)
            {
                c[pos++]=b[j];
                j++;
                continue;
            }
            if(j>=lenb)
            {
                c[pos++]=a[i]+x;
                i++;
                continue;
            }

            _int p = a[i]+x;
            _int q = b[j];

            if(p < q)
            {
                c[pos++]=p;
                i++;
            }
            else
            {
                c[pos++]=q;
                j++;
            }
        }
        return lena+lenb;
    }

    void pushup(int node)
    {

        sizer[node]=fun(node,r[node<<1],sizer[node<<1],r[node<<1|1],sizer[node<<1|1],node<<1|1,r[node]);
        sizel[node]=fun(node,l[node<<1|1],sizel[node<<1|1],l[node<<1],sizel[node<<1],node<<1,l[node]);

        int len = sizel[node<<1|1];
        for(int i=0;i<len;i++)
        {
            int pos2 = upper_bound(r[node<<1],r[node<<1]+sizer[node<<1],upp-l[node<<1|1][i])-r[node<<1];
            if(pos2==0)
                break;

            int pos = lower_bound(r[node<<1],r[node<<1]+sizer[node<<1],low-l[node<<1|1][i])-r[node<<1];

            ans+=pos2-pos;
        }

        range[node]=range[node<<1]+range[node<<1|1];

    }

    void build(int node,int start,int end)
    {
        if(start==end)
        {
            l[node]=new _int{num[start]};
            sizel[node]=1;
            r[node]=new _int{num[start]};
            sizer[node]=1;
            range[node]=num[start];

            if(range[node]<=upp&&range[node]>=low)
                ans++;

            return;
        }

        int mid = (start+end)>>1;
        build(node<<1,start,mid);
        build(node<<1|1,mid+1,end);

        pushup(node);
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档