zoukankan      html  css  js  c++  java
  • 树状数组【洛谷3374】

    【题目】

    lowbit:一个数二进制中的最后一个1

    int lowbit(int x){return x & -x;}

    如 :100111010→10,1011000→1000

    a[i]:不解释。

    sum[i]:a[i - lowbit(i) + 1].....a[i]的和

    xask(i,j):a[i].....a[j]的值,前缀和实现。

    可以得到:①sum[i] = sum[i - lowbit(i)] + xask(i - lowbit(i) + 1,i)

    ask(i):a[1]......a[i]的值

    故有:

    int ask(int x){
        int res = 0;
        for(int i = x;i > 0;i -= lowbit(i))
            res += sum[i];
        return res;
    }

    可以得到:a[i]...a[j]的值为ask(j) - ask(i - 1)

    修改:②将a[i] 增加delta:while(i <= n)sum[i] += delta,i += lowbit(i);


    证明:②:

    表一:

    i 1 2 3 4 5 6 7 8 9 10 11 12
    sum[i]代表范围 1    1..2 3    1..4 5    5..6 7    1..8 9    9..10 11    9..12

     首先:lowerbit(a) < lowerbit(a + lowerbit(a))

    证明:

       1  0  1  0  1  0  0

    +                      1  0  0

    ------------------------------

              1  0  1  1  0  0  0

    a加上lowerbit(a)后,最后一个“1”肯定没了,其后也不会多出“1”。

    所以

    int a = xxx;
    int b = a + lowerbit(a);
    则 a - lowerbit(a) < b - lowerbit(b)

    所以,当你要把a[x]加上某一个值时,重复执行x += lowerbit(x),其sum[x]指示的范围始终包括i

    这一点由表一可以验证。

    故有以下代码:

    void add(int w,int d){
        for(int i = w;i <= n;i += lowbit(i))
            sum[i] += d;
    }

    最后AC代码:

    #include <cstdio>
    #define N 1000001
    int a[N],n,m,sum[N],tmp[N];
    int lowbit(int x){return x & -x;}
    int xask(int x,int y){return tmp[y] - tmp[x - 1];}
    void creat(){for(int i = 1;i <= n;i++)sum[i] = xask(i - lowbit(i) + 1,i);}
    void add(int w,int d){
        for(int i = w;i <= n;i += lowbit(i))
            sum[i] += d;
    }
    int ask(int x){
        int res = 0;
        for(int i = x;i > 0;i -= lowbit(i))
            res += sum[i];
        return res;
    }
    int main()
    {
        tmp[0] = 0;
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;i++)
            scanf("%d",&a[i]),tmp[i] = tmp[i - 1] + a[i];
        creat();
        for(int i = 1;i <= m;i++){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            if(x == 1)add(y,z);
            else if(x == 2)printf("%d
    ",ask(z) - ask(y - 1));
        }
        return 0;
    }

     end.

  • 相关阅读:
    vue 如何在循环中 "监听" 的绑定v-model数据
    验证正则表达式,同时验证手机号码和固定电话号码
    vue 图片上传功能
    localStorage使用总结
    vue2.0 父子组件通信 兄弟组件通信
    SVN使用教程总结
    详解SVN 的使用
    彻底理解setTimeout()
    如何实现一个HTTP请求库——axios源码阅读与分析 JavaScript
    2、Zookeeper原理及应用汇总
  • 原文地址:https://www.cnblogs.com/frankying/p/8597103.html
Copyright © 2011-2022 走看看