• leetCode


    模板库

    https://github.com/EndlessCheng/codeforces-go/blob/master/copypasta/segment_tree.go

    Wiki

    https://oi-wiki.org/ds/seg/#%E7%BA%BF%E6%AE%B5%E6%A0%91%E7%9A%84%E5%8C%BA%E9%97%B4%E4%BF%AE%E6%94%B9%E4%B8%8E%E6%87%92%E6%83%B0%E6%A0%87%E8%AE%B0

    树状数组

    将所有节点上的十进制改为了二进制表示

    C[1] = A[1]; C[2] = A[1] + A[2]; C[3] = A[3]; C[4] = A[1] + A[2] + A[3] + A[4]; C[5] = A[5]; C[6] = A[5] + A[6]; C[7] = A[7]; C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]; 可以发现,这颗树是有规律的 C[i] = A[i - 2(k)+1] + A[i - 2(k)+2] + ... + A[i]; //k为i的二进制中从最低位到高位连续零的长度

    • 我们只需要算出当前节点下标二进制表示的最低位1的位置,然后算出只保留这个1得到的数,结合当前节点的下标,就可以计算出下一个需要修改的节点的下标了

    • 这里我们设计一个函数lowbit(int x)用于计算给定一个下标x,返回:其二进制下标只保留最低位1会得到的那个数

     
    

    //借鉴前人智慧,可以轻松得到 int lowbit(x){return x&(-x);}

    简单解释一下为什么可以通过x&(-x)得到这个数

    我们知道,对于一个数的负数就等于对这个数取反+1

    以二进制数11010为例:11010的补码为00101,加1后为00110,两者相与便是最低位的1

    其实很好理解,补码和原码必然相反,所以原码有0的部位补码全是1,补码再+1之后由于进位那么最末尾的1和原码

    最右边的1一定是同一个位置(当遇到第一个1的时候补码此位为0,由于前面会进一位,所以此位会变为1)

    所以我们只需要进行a&(-a)就可以取出最低位的1了

     
    

    //tr表示树状节点 /** * 用于进行树状数组的更新过程 * @param x: 被修改的数组下标 * @param val: 修改量(负数代表减少) */ public void add(int x,int val){ for(int i=x;i<=n;i+=lowbit(i)){ tr[i] += val; } }

     
    

    //tr表示树状节点 /** * 用于进行前缀求和的查询过程 * @param x: 需要查询的数组下标x * @return 计算从0节点到x节点之间所有值之和 */ public int pre_sum(int x){ int sum = 0; for(int i=x;i>0;i-=lowbit(i)){ sum += tr[i]; } return sum; }

    307. 区域和检索 - 数组可修改 - 力扣(LeetCode) (leetcode-cn.com)

    线段树

    • 上图中,每个区间都是一个节点,每个节点存自己对应的区间的统计信息。

    1. 线段树的点修改:

      1. 假设要修改[5]的值,可以发现,每层只有一个节点包含[5],所以修改了[5]之后,只需要每层更新一个节点就可以线段树每个节点的信息都是正确的。复杂度O(log2(n)).

    2. 线段树的区间查询

      1. n>=3时,一个[1,n]的线段树可以将[1,n]的任意子区间[L,R]分解为不超过2*log2(n-1)个区间。

    3. 线段树的区间修改:

      1. 线段树的区间修改也是将区间分成子区间,但是要加一个标记,称作懒惰标记。

      2. 如果要给一个区间的所有值都加上1,那么,实际上并没有给这个区间的所有值都加上1,而是打个标记,记下来,这个节点所包含的区间需要加1.打上标记后,要根据标记更新本节点的统计信息,比如,如果本节点维护的是区间和,而本节点包含5个数,那么,打上+1的标记之后,要给本节点维护的和+5。这是向下延迟修改,但是向上显示的信息是修改以后的信息,所以查询的时候可以得到正确的结果。有的标记之间会相互影响,所以比较简单的做法是,每递归到一个区间,首先下推标记(若本节点有标记,就下推标记),然后再打上新的标记,这样仍然每个区间操作的复杂度是O(log2(n))。

    4. 实现

    • 定义

        1. class Solution {
        2. static int[][] tree;
        3. static int[][] cnt;
        4. public String minInteger(String num, int k) {
        5. }
        6. void update(int index,int i,int l,int r,int L,int R,int val){
        7. if(L<=l&&r<=R){
        8. cnt[i][index]+=val;
        9. tree[i][index]+=val;
        10. return;
        11. }
        12. if(cnt[i][index]!=0){
        13. cnt[i][index<<1]+=cnt[i][index];
        14. tree[i][index<<1]+=cnt[i][index];
        15. cnt[i][index<<1|1]+=cnt[i][index];
        16. tree[i][index<<1|1]+=cnt[i][index];
        17. cnt[i][index]=0;
        18. }
        19. int m =(l+r)>>1;
        20. if(L<=m){
        21. update(index<<1, i, l, m, L, R, val);
        22. }
        23. if(R>m){
        24. update(index<<1|1, i, m, r, L, R, val);
        25. }
        26. tree[i][index]=Math.min(tree[i][index<<1],tree[i][index<<1|1]);
        27. }
        28. int query(int index,int i,int l,int r,int L,int R){
        29. if(L<=l&&r<=R){
        30. return tree[i][index];
        31. }
        32. if(cnt[i][index]!=0){
        33. cnt[i][index<<1]+=cnt[i][index];
        34. tree[i][index<<1]+=cnt[i][index];
        35. cnt[i][index<<1|1]+=cnt[i][index];
        36. tree[i][index<<1|1]+=cnt[i][index];
        37. cnt[i][index]=0;
        38. }
        39. int m =(l+r)>>1;
        40. int res = Integer.MAX_VALUE;
        41. if(L<=m){
        42. res = Math.min(res,query(index<<1, i, l, m, L, R));
        43. }
        44. if(R>m){
        45. res = Math.min(res,query(index<<1|1, i, m, r, L, R));
        46. }
        47. return res;
        48. }
        49. }
  • 相关阅读:
    抽象类和抽象方法
    P1182 数列分段 Section II
    文件删除如何恢复?简单的方法
    【教3妹学算法】相似度为 K 的字符串
    CTFhub-RCE-远程包含
    【群智能算法改进】一种改进的棕熊优化算法 IBOA算法[1]【Matlab代码#64】
    多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测
    【Azure Developer】使用 CURL 获取 Key Vault 中 Secrets 中的值
    Dockerfile关键词
    Standardized QCI characteristics
  • 原文地址:https://blog.csdn.net/skycqd/article/details/133186660