树状数组维护前缀和

树状数组是用来维护序列前缀和的数据结构。它的修改与求和都是O(logn)的,效率非常高。

我们设序列为A,则树状数组c中,c[i]记录序列A的区间[ i-lowbit(i)+1 , i ]中所有数的和。 (树状数组是个好东西ovo) 

树状数组在进行区间操作时,要从上到下访问,进行单点操作时,要从下到上访问。 

树状数组维护序列前缀和的模版如下:

#include <iostream>
#include <cstdio>
#define maxn 500005
using namespace std;

int n,m;
int c[maxn];//c[i]存序列a中i-lowbit(i)+1到i的所有数的和(树状数组)

int read()
{
    int f=1,x=0;
    char ch;
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘)f=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return f*x;
}

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

void update(int x,int y)
{
    while(x<=n)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}//将序列a[x]加上y

int sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}//求序列1-x的和

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        //a[i]=read();
        int v=read();
        update(i,v);
    }
    for(int i=1;i<=m;i++)
    {
        int op,x,y;
        op=read();x=read();y=read();
        if(op==1)
        {
            update(x,y);
        }
        if(op==2)
        {
            int ans=sum(y)-sum(x-1);
            printf("%d\n",ans);
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/Bw-Orzzzzz/p/10829093.html

时间: 2024-10-12 21:48:27

树状数组维护前缀和的相关文章

树状数组维护前缀和、后缀和、个数|牛牛的Link Power

思路 另线段树做法:https://www.cnblogs.com/fisherss/p/12287606.html F题树状数组维护前缀即可 题目地址 https://ac.nowcoder.com/acm/contest/3004/F #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5+100; int n; char s[maxn]; const ll mod =

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以

51Nod 1272最大距离 (树状数组维护前缀最小值)

题目链接 最大距离 其实主流解法应该是单调栈--我用了树状数组. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 7 const int N = 100010; 8 9 struct node{ 10 int x, y; 11 friend bool operator < (const node &a, c

ACdreamoj 1011(树状数组维护字符串hash前缀和)

题目链接:http://acdream.info/problem? pid=1019 题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符.另外一种查询某个连续子序列是否是回文串: 解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串.还有一个是反串用于比較.比較时候乘以对应的p倍数推断是否相等. 刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(

Codeforces1076E. Vasya and a Tree(dfs+离线+树状数组维护)

题目链接:传送门 题目: E. Vasya and a Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Vasya has a tree consisting of n vertices with root in vertex 1. At first all vertices has 0 written on it.

HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gcd种类不超过loga[i]种). 预处理gcd如下代码,感觉真的有点巧妙... 1 for(int i = 1; i <= n; ++i) { 2 int x = a[i], y = i; 3 for(int j = 0; j < ans[i - 1].size(); ++j) { 4 int g

[ACM] hdu 5147 Sequence II (树状数组,前缀和,后缀和)

Sequence II Problem Description Long long ago, there is a sequence A with length n. All numbers in this sequence is no smaller than 1 and no bigger than n, and all numbers are different in this sequence. Please calculate how many quad (a,b,c,d) satis

2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ&#39;s Salesman 【离散化+树状数组维护区间最大值】

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 919    Accepted Submission(s): 290 Problem Description YJJ is a salesman who h

Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) C. Fountains 【树状数组维护区间最大值】

题目传送门:http://codeforces.com/contest/799/problem/C C. Fountains time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. The