首页 > 其他分享 >lc327 区间和的个数

lc327 区间和的个数

时间:2024-03-16 11:13:33浏览次数:18  
标签:node return int TYPE 个数 son lc327 区间 data

给定数组nums[n]和整数lower与upper,求nums[n]中,元素之和在[lower,upper]范围内的子数组个数。
1<=n<=1e5; nums[i]在int范围内; -1e5<=lower<=upper<=1e5; 答案在int范围内

子数组的和可以用前缀和来快速求出,假设当前位置对应的前缀和为y,前面某处对应的前缀和为x,满足lower<=y-x<=upper,变形得y-upper<=x<=y-lower,需要找满足该条件的x的个数,套平衡树模板即可。

template <typename TYPE>
struct Treap {
    struct Node {
        TYPE data, sum;
        int rnd, siz, dup, son[2];
        void init(const TYPE & d) {
            data = sum = d;
            rnd = rand();
            siz = dup = 1;
            son[0] = son[1] = 0;
        }
    };
    Treap(size_t sz, bool multi):multiple(multi) {
        node.resize(sz);
        reset();
    }
    int newnode(const TYPE & d) {
        total += 1;
        node[total].init(d);
        return total;
    }
    void reset() { root = total = 0; }
    void maintain(int x) {
        node[x].siz = node[x].dup;
        node[x].sum = node[x].data * node[x].dup;
        if (node[x].son[0]) {
            node[x].siz += node[node[x].son[0]].siz;
            node[x].sum += node[node[x].son[0]].sum;
        }
        if (node[x].son[1]) {
            node[x].siz += node[node[x].son[1]].siz;
            node[x].sum += node[node[x].son[1]].sum;
        }
    }
    void rotate(int d, int &r) {
        int k = node[r].son[d^1];
        node[r].son[d^1] = node[k].son[d];
        node[k].son[d] = r;
        maintain(r);
        maintain(k);
        r = k;
    }
    void insert(const TYPE &data, int &r, bool &ans) {
        if (r) {
            if (!(data < node[r].data) && !(node[r].data < data)) {
                ans = false;
                if (multiple) {
                    node[r].dup += 1;
                    maintain(r);
                }
            } else {
                int d = data < node[r].data ? 0 : 1;
                insert(data, node[r].son[d], ans);
                if (node[node[r].son[d]].rnd > node[r].rnd) {
                    rotate(d^1, r);
                } else {
                    maintain(r);
                }
            }
        } else {
            r = newnode(data);
        }
    }
    void getkth(int k, int r, TYPE& data) {
        int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
        int y = node[r].dup;
        if (k <= x) {
            getkth(k, node[r].son[0], data);
        } else if (k <= x + y) {
            data = node[r].data;
        } else {
            getkth(k-x-y, node[r].son[1], data);
        }
    }
	TYPE getksum(int k, int r) {
        if (k <= 0 || r == 0) return 0;
		int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
		int y = node[r].dup;
        if (k <= x) return getksum(k, node[r].son[0]);
        if (k <= x+y) return node[node[r].son[0]].sum + node[r].data * (k-x);
        return node[node[r].son[0]].sum + node[r].data * y + getksum(k-x-y,node[r].son[1]);
	}
    void erase(const TYPE& data, int & r) {
        if (r == 0) return;
        int d = -1;
        if (data < node[r].data) {
            d = 0;
        } else if (node[r].data < data) {
            d = 1;
        }
        if (d == -1) {
            node[r].dup -= 1;
            if (node[r].dup > 0) {
                maintain(r);
            } else {
                if (node[r].son[0] == 0) {
                    r = node[r].son[1];
                } else if (node[r].son[1] == 0) {
                    r = node[r].son[0];
                } else {
                    int dd = node[node[r].son[0]].rnd > node[node[r].son[1]].rnd ? 1 : 0;
                    rotate(dd, r);
                    erase(data, node[r].son[dd]);
                }
            }
        } else {
            erase(data, node[r].son[d]);
        }
        if (r) maintain(r);
    }
    int ltcnt(const TYPE& data, int r) {
        if (r == 0) return 0;
        int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
        if (data < node[r].data) {
            return ltcnt(data, node[r].son[0]);
        }
        if (!(data < node[r].data) && !(node[r].data < data)) {
            return x;
        }
        return x + node[r].dup + ltcnt(data, node[r].son[1]);
    }
    int gtcnt(const TYPE& data, int r) {
        if (r == 0) return 0;
        int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
        if (data > node[r].data) {
            return gtcnt(data, node[r].son[1]);
        }
        if (!(data < node[r].data) && !(node[r].data < data)) {
            return x;
        }
        return x + node[r].dup + gtcnt(data, node[r].son[0]);
    }
    int count(const TYPE& data, int r) {
        if (r == 0) return 0;
        if (data < node[r].data) return count(data, node[r].son[0]);
        if (node[r].data < data) return count(data, node[r].son[1]);
        return node[r].dup;
    }
    void prev(const TYPE& data, int r, TYPE& result, bool& ret) {
        if (r) {
            if (node[r].data < data) {
                if (ret) {
                    result = max(result, node[r].data);
                } else {
                    result = node[r].data;
                    ret = true;
                }
                prev(data, node[r].son[1], result, ret);
            } else {
                prev(data, node[r].son[0], result, ret);
            }
        }
    }
    void next(const TYPE& data, int r, TYPE& result, bool& ret) {
        if (r) {
            if (data < node[r].data) {
                if (ret) {
                    result = min(result, node[r].data);
                } else {
                    result = node[r].data;
                    ret = true;
                }
                next(data, node[r].son[0], result, ret);
            } else {
                next(data, node[r].son[1], result, ret);
            }
        }
    }
    vector<Node> node;
    int root, total;
    bool multiple;
    bool insert(const TYPE& data) {
        bool ret = true;
        insert(data, root, ret);
        return ret;
    }
    bool kth(int k, TYPE &data) {
        if (!root || k <= 0 || k > node[root].siz)
            return false;
        getkth(k, root, data);
        return true;
    }
	TYPE ksum(int k) {
        assert(root && k>0 && k<=node[root].siz);
        return getksum(k, root);
    }
    int count(const TYPE &data) {
        return count(data, root);
    }
    int size() const {
        return root ? node[root].siz : 0;
    }
    void erase(const TYPE& data) {
        return erase(data, root);
    }
    int ltcnt(const TYPE& data) {
        return ltcnt(data, root);
    }
    int gtcnt(const TYPE& data) {
        return gtcnt(data, root);
    }
    bool prev(const TYPE& data, TYPE& result) {
        bool ret = false;
        prev(data, root, result, ret);
        return ret;
    }
    bool next(const TYPE& data, TYPE& result) {
        bool ret = false;
        next(data, root, result, ret);
        return ret;
    }
};

class Solution {
public:
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        int n = nums.size();
        vector<long long> pre(n);
        for (int i = 0; i < n; i++)
            pre[i] = nums[i];
        partial_sum(pre.begin(), pre.end(), pre.begin());
        Treap<long long> tp(100005, true);
        tp.insert(0);
        int ans = 0;
        for (auto i : pre) {
            ans += tp.size() - tp.ltcnt(i-upper) - tp.gtcnt(i-lower);
            tp.insert(i);
        }
        return ans;
    }
};

标签:node,return,int,TYPE,个数,son,lc327,区间,data
From: https://www.cnblogs.com/chenfy27/p/18076814

相关文章

  • abc135d 模13余5的数的个数
    给定一个由0~9以及?组成的字符串,其中的?可以替换成0~9中任意1个数字,问有多少种情况使得这个数字模13的余数为5?结果对1e9+7取模。注意允许s有前导0。1<=|s|<=1e5记dp[i][j]表示前i个数字构成的数,模13余j的方案数。如果s[i]是数字,直接转移;如果是问题,枚举0~9所有可能分别枚举,总时间......
  • 力扣刷题Days16 - 191.位1的个数(js)
    目录1,题目2,代码2.1逐位判断核心代码2.1.2逐位判断22.2位运算优化3,学习与总结1,题目编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为'1'的个数(也被称为汉明重量)。2,代码2.1逐位判断/***@param{number}n-apositivein......
  • 记录学生的姓名、编号以及总分,输入n,代表学生个数,要求用结构体泡排序将学生信息按学生
    //记录学生的姓名、编号以及总分,输入n,代表学生个数,要求用结构体,//用冒泡排序将学生信息按学生总分从低到高排名,将学生信息打印出来;//并输入一个总分x,用折半查找查找所有总分为x的学生,并将学生信息打印出来#include<stdio.h>#include<stdlib.h>structStudent{ ch......
  • C++ | 蓝桥题库区间或(位运算)
    一开始看题解很晕,这里采用前缀和方式的思想是:按位贡献,将答案分成32份(1e9最多32位二进制数)这样才有的prefix[32][N]前缀和数组,求的是第i位数第w位上的和。(1<<w)1左移w位相当于2的w次方,prefix[w][r]-prefix[w][l-1]相当于[l,r]这段距离上有1就让ans加上1,没有就不加。#inc......
  • 【PG】对比两个数据中对象
    #!/bin/bash####################################################################################################################################Name:Compare2PostgresDBs##Description:Compare2PostgresDBsTables,Indexes,andFunctions.Incas......
  • 蓝桥练习题-K倍区间
    16.k倍区间-蓝桥云课(lanqiao.cn)首先,看到这个题,想到暴力求解,但显然,数据过大,暴力法过不了;然后看到了一个办法:对所有元素的前缀和取K的模,若s[i],s[j]相同,则在j-1到i的区间内,区间和为K的倍数。C++代码:#include<iostream>#include<queue>usingnamespacestd;ty......
  • lc2035 将数组分成两个数组并最小化数组和的差
    给你一个长度为2n的整数数组,需要将它分成两个长度为n的数组,分别求出两个数组的和,并最小化两个数组和之差的绝对值。nums中每个元素都需要放入两个数组之一,求最小的数组和之差。1<=n<=15;-1E7<=nums[i]<=1E7直接暴搜的话最坏时间复杂度是O(2^30),会TLE,可以使用双向dfs优化,每次df......
  • leedcode-完全二叉树的节点个数
    自己写的,使用广度优先BFS,迭代:classSolution:defcountNodes(self,root:Optional[TreeNode])->int:#如果根节点为空,则树中节点数为0ifnotroot:return0#初始化队列,并将根节点放入队列中queue=[root]......
  • 2024/3/11打卡管道(14届蓝桥杯省赛)——二分+区间合并
    目录题目思路代码题目有一根长度为 len的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。一开始管道是空的,位于 Li 的阀门会在  时刻打开,并不断让水流入管道。对于位于  的阀门,它流入的水在 时刻会使得......
  • shell脚本中main函数中$#获取不到脚本传入参数个数浅析
    Linux的shell脚本,有时候我们在运行shell脚本时会给脚本传入参数,出于逻辑上的严谨,在脚本中可能会做一些逻辑判断或处理,例如判断脚本传入参数的个数。一般我们会用$#获取传入参数的个数,假如,我们在shell脚本的main函数中去判断脚本传入参数的个数,类似如下所示:.........function mai......