• 树状数组


    树状数组实际上是个数组,维护一个区间,支持查询区间的前缀和,以及修改单点的值。

    定义lowbit(x)=x&(-x),表示将x的二进制数只保留从右往左数的第一个1后的数字。

    设树状数组为C,规定C[i]维护区间[i-lowbit(i)+1,i]的数字和。因此,要访问C[i]维护的区间的前一个区间,则访问C[i-lowbit(i)];要访问包含C[i]维护的区间的区间,则访问C[i+lowbit(i)](规律)。

    因此,区间查询某前缀[1,i],则不断查询C[i]再查询C[i]前一个区间C[i-lowbit(i)]。要单点修改,则不断更改C[i]和包含它的C[i+lowbit(i)]。

    luogu3374 【模板】树状数组1

    题目大意:已知一个数列,你需要进行下面两种操作:1.将某一个数加上x;2.求出某区间每一个数的和。

    1操作就是规定动作;2操作输出r前缀和减去l-1前缀和。

    #include <cstdio>
    #include <cassert>
    using namespace std;
    
    const int MAX_N = 500010;
    int C[MAX_N], A[MAX_N];
    int N;
    
    int Lowbit(int x)
    {
        return x&(-x);
    }
    
    int Sum(int p)
    {
        int ans = 0;
        while (p)
        {
            ans += C[p];
            p -= Lowbit(p);
        }
        return ans;
    }
    
    void Modify(int p, int delta)
    {
        while (p <= N)
        {
            C[p] += delta;
            p += Lowbit(p);
        }
    }
    
    void Init()
    {
        for (int i = 1; i <= N; i++)
            Modify(i, A[i]);
    }
    
    int main()
    {
    #ifdef _DEBUG
        freopen("c:\noi\source\input.txt", "r", stdin);
    #endif
        int m, op, p, delta, l, r;
        scanf("%d%d", &N, &m);
        for (int i = 1; i <= N; i++)
            scanf("%d", i + A);
        Init();
        while (m--)
        {
            scanf("%d", &op);
            switch (op)
            {
            case 1:
                scanf("%d%d", &p, &delta);
                Modify(p, delta);
                break;
            case 2:
                scanf("%d%d", &l, &r);
                printf("%d
    ", Sum(r) - Sum(l - 1));
                break;
            default:
                assert(0);
            }
        }
        return 0;
    }

    luogu3368 【模板】树状数组2

    题目大意:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数数加上x;2.求出某一个数的和。

    先不考虑树状数组的问题。设原序列为A,令B[i]=A[i]-A[i-1]。查询点,相当于A[i]=sum (foreach j=1 to i)B[i]。更改一个区间[i,j],就相当于B[i]+1,B[j+1]-1。用树状数组C维护B,就可满足树状数组“单点修改,区间查询”的操作了。

    #include <cstdio>
    #include <cstring>
    #include <cassert>
    using namespace std;
    
    const int MAX_N = 500010;
    int A[MAX_N], B[MAX_N], C[MAX_N];
    int N;
    
    int Lowbit(int x)
    {
        return x&(-x);
    }
    
    int Sum(int p)
    {
        int sum = 0;
        while (p)
        {
            sum += C[p];
            p -= Lowbit(p);
        }
        return sum;
    }
    
    void Update(int p, int delta)
    {
        while (p <= N)
        {
            C[p] += delta;
            p += Lowbit(p);
        }
    }
    
    int main()
    {
    #ifdef _DEBUG
        freopen("c:\noi\source\input.txt", "r", stdin);
    #endif
        int opCnt, op, l, r, k, x;
        scanf("%d%d", &N, &opCnt);
        for (int i = 1; i <= N; i++)
        {
            scanf("%d", i + A);
            B[i] = A[i] - A[i - 1];
            Update(i, B[i]);
        }
        while (opCnt--)
        {
            scanf("%d", &op);
            switch (op)
            {
            case 1:
                scanf("%d%d%d", &l, &r, &k);
                Update(l, k);
                Update(r + 1, -k);
                break;
            case 2:
                scanf("%d", &x);
                printf("%d
    ", Sum(x));
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    洛谷 P5110 块速递推
    洛谷 P3868 [TJOI2009]猜数字
    Codeforces 343D Water Tree
    Codeforces 915E Physical Education Lessons
    洛谷 P2787 语文1(chin1)- 理理思维
    洛谷 P4344 [SHOI2015]脑洞治疗仪
    洛谷 P3338 [ZJOI2014]力
    【模板】珂朵莉树(ODT)(Codeforces 896C Willem, Chtholly and Seniorious)
    【模板】FFT
    Solution of CF911G Mass Change Queries
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8445977.html
Copyright © 2020-2023  润新知