Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >进阶版树状数组

进阶版树状数组

作者头像
glm233
发布于 2020-09-28 02:30:25
发布于 2020-09-28 02:30:25
45300
代码可运行
举报
运行总次数:0
代码可运行

我们都知道树状数组一般有两种形式

1.最为传统的版本,支持区间求和,单点修改

2.差分树状数组 支持区间修改,单点查询

而进阶版树状数组 可支持 区间求和,区间修改

其原理是:

设tree[i]=a[i]-a[i-1](差分),那么容易得到:

tree[1]+tree[2]+……+tree[i]=a[i]这个公式

维护tree数组即可以实现区间修改了。

接下来是区间查询的实现问题

我们已经推出了一个公式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
tree[1]+tree[2]+……tree[i]=a[i]

那么,对于1到r的区间和,即为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 a[1]+a[2]+……+a[r-1]+a[r]
//用上方公式推导得出
=tree[1]+(tree[1]+tree[2])+……+(tree[1]+……+tree[r])
//根据加法交换律与结合律:
=(tree[1]*(r))+(tree[2]*(r-1))+……(tree[r]*1)
//那么:
=r*(tree[1]+tree[2]+……+tree[r])-(tree[1]*0+tree[2]*1+……+tree[r]*(r-1))

看到这里,是不是已经很清晰了呢?

对于a的树状数组(差分)tree,建立一个新的树状数组tree1使得:

tree1[i]=tree[i]*(i-1)

之后,x到y的区间和即为:

(y*query(tree,y)-(x-1)*query(tree,x-1))-(query(tree1,y)-query(tree1,x-1))

P3372 【模板】线段树 1

这种树状数组可以实现线段树的某些功能

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<bits/stdc++.h>
#define rg register
#define inf 2147483647
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
#define maxn 100005
const double eps=1e-8;
using namespace std;
inline ll read()
{
    char ch=getchar();ll s=0,w=1;
    while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();}
    while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
    return s*w;
}
inline void write(ll x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+48);
}
ll n,m;
ll tree[maxn],tree1[maxn];
inline ll lb(ll x)
{
    return x&-x;
}
inline void add(ll *tree,ll x,ll k)
{
    for(;x<=n;x+=lb(x))
    {
        tree[x]+=k;
    }
}
inline ll query(ll *tree,ll x)
{
    ll ans=0;
    for(;x;x-=lb(x))
    {
        ans+=tree[x];
    }
    return ans;
}
int main()
{
    n=read(),m=read();
    ll now,last=0;
    for( rg ll i=1;i<=n;i++)
    {
        now=read();
        add(tree,i,now-last);
        add(tree1,i,(now-last)*(i-1));
        last=now;
    }
    for(rg ll i=1;i<=m;i++)
    {
        ll x;
        x=read();
        if(x==1)
        {
            ll a,b,c;
            a=read(),b=read();c=read();
            add(tree,a,c);
            add(tree,b+1,-c);
            add(tree1,a,c*(a-1));
            add(tree1,b+1,-c*b);
        }
        else if(x==2)
        {
           ll  a,b;
           a=read(),b=read();
           cout<<b*query(tree,b)-(a-1)*query(tree,a-1)-(query(tree1,b)-query(tree1,a-1))<<endl;
        }
    }
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/06/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
洛谷P3372 【模板】线段树 1(树状数组)
$= sum_{i = 1}^x (x+1)d_i - \sum_{i = 1}^x id_i$
attack
2018/10/08
5900
UESTC 1584 Washi与Sonochi的约定【树状数组裸题+排序】
题目链接:UESTC 1584 Washi与Sonochi的约定 题意:在二维平面上,某个点的ranked被定义为x坐标不大于其x坐标,且y坐标不大于其y坐标的怪物的数量。(不含其自身),要求输出n行,每行一个整数,分别代表rank为0~n^1的怪物数量。 分析:树状数组+排序,其实就是道树状数组的裸题,和poj2352是同题,套个板子就可以过 思路就是把所有的坐标读入之后,按照x为第优先级,y为第二优先级,都是从小到大排序,只从从0~n-1扫一遍,此时(i时)树状数组里的点的x值, 都不比val[i].
Angel_Kitty
2018/04/09
6620
Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) B. Cards Sorting 树状数组+技巧
Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this integer is between 1 and 100 000, inclusive. It is possible that some cards have the same integers on them.
glm233
2020/09/28
4650
原来树状数组可以这么简单?
首先最容易想到的方法就是先求出前缀和sum[i],然后区间[a,b]的和就可以直接通过sum[b]-sum[a-1]得到。
小K算法
2022/06/09
4280
原来树状数组可以这么简单?
Codeforces Round #547 (Div. 3)C. Polycarp Restores Permutation
An array of integers p1,p2,…,pnp1,p2,…,pn is called a permutation if it contains each number from 11 to nn exactly once. For example, the following arrays are permutations: [3,1,2][3,1,2], [1][1], [1,2,3,4,5][1,2,3,4,5] and [4,3,1,2][4,3,1,2]. The following arrays are not permutations: [2][2], [1,1][1,1], [2,3,4][2,3,4].
glm233
2020/09/28
5320
洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)
也就是我们需要解决这么一个问题:两个操作, 矩形加矩形求和,而且前者都在后者的前面执行
attack
2019/03/11
5910
详解树状数组(C/C++)
树状数组(Binary Indexed Tree,简称BIT或Fenwick Tree)是一种用于高效处理数据序列的算法数据结构。它能够支持两个主要操作:单点更新和区间求和,这两个操作的时间复杂度都能达到O(log n),其中 n 是数据序列的长度。树状数组非常适合处理那些需要频繁更新和查询区间和的问题。
摆烂小白敲代码
2024/09/23
5640
详解树状数组(C/C++)
10:Challenge 3(树状数组直接修改)
总时间限制: 10000ms单个测试点时间限制: 1000ms内存限制: 262144kB描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)修改数列中的一个数 (2)求数列中某连续一段的和 输入第一行两个正整数N和M。 第二行N个整数表示这个数列。 接下来M行,每行开头是一个字符,若该字符为'M',则表示一个修改操作,接下来两个整数x和y,表示把x位置的值修改为y;若该字符为'Q',则表示一个询问操作,接下来两个整数x和y,表示求[x,y]这段区间的和。输出对每一个询问操作单独输出一行,
attack
2018/04/12
1.3K0
T4701 【卜卜】树状数组模板
题目描述 在二维平面内给定n个点: 0 x y v表示给(x,y)的权值减去v 1 x y v表示给(x,y)的权值加上v 然后有m个操作 0 x y v , 1 x y v 意义如上 2 a b c d表示询问左上角为(a,b) , 右下角为(c,d)的矩阵权值和 输入输出格式 输入格式: 第一行一个数n 后n行 每行三个数 type x y 意义见上 然后一个数m表示操作数 后m行 第一个数为type 若type=2 则接四个数 a,b,c,d 意义见上 否则接三个数 x,y,v 意义见上 输出格式:
attack
2018/04/12
6670
树状数组、线段树与RMQ
binary index tree 来自OI-wiki的图,我记得刘汝佳书里也有,不过那本书不在我手边
千灵域
2022/06/17
7530
树状数组、线段树与RMQ
算法学习笔记(2)树状数组【转】
树状数组(Binary Index Tree, BIT)也是很多OIer心中最简洁优美的数据结构之一。最简单的树状数组支持两种操作,时间复杂度均为 :
Chuanrui 初见之旅
2022/11/14
4820
算法学习笔记(2)树状数组【转】
BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1
attack
2018/07/27
2920
HDU6447(离散化扫描线+树状数组)
YJJ要从(0,0)点走到(1e9,1e9),当他处于点(x,y)时他只能走到(x,y+1)或(x+1,y)或(x+1,y+1)。而坐标轴上有n个村庄,如果他路过某个村庄就会赚到特定数量的钱,可是处于点(xk,yk)的村庄只会跟从点(xk-1,yk-1)走过来的人交易。求YJJ走完旅途能得到的最大钱数。
ACM算法日常
2019/04/25
6010
PAT (Basic Level) Practice (中文)1030 完美数列 (25 分)
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
glm233
2020/09/28
3670
BZOJ5484(LIS性质+树状数组)
FJ有N(1≤N≤10^5)头奶牛(分别用1…N编号)排成一行。FJ喜欢他的奶牛以升序排列,不幸的是现在她们的顺序被打乱了。在过去FJ曾经使用一些诸如“冒泡排序”的开创性的算法来使他的奶牛排好序,但今天他想偷个懒。
ACM算法日常
2019/04/25
6530
树状数组-从入门到拓展(转载非原创)
转载来源:https://www.cnblogs.com/AKing-/p/15311440.html
xlj
2021/09/20
5050
Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K=1,读入l、r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同 K=2,读入l,r表示询问l~r之间能见到多少种树 (l,r>0) 格式 输入格式 第一行n,m表示道路总长为n,共有m个操作 接下来m行为m个操作 输出格式 对于每个k=2输出一个答案 样例1 样例输入1 5 4 1 1 3
Angel_Kitty
2018/04/09
1.7K0
Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
洛谷P2345 奶牛集会
题目背景 MooFest, 2004 Open 题目描述 约翰的N 头奶牛每年都会参加“哞哞大会”。哞哞大会是奶牛界的盛事。集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等。它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没有两头奶牛的坐标是相同的。奶牛们的叫声很大,第i 头和第j 头奶牛交流,会发出max{Vi; Vj}×|Xi − Xj | 的音量,其中Vi 和Vj 分别是第i 头和第j 头奶牛的听力。假设每对奶牛之间同时都在说话,请计算所有奶牛产生的音量之和是多少。 输入输出格式 输入格式
attack
2018/04/11
8160
洛谷P2345 奶牛集会
codechef Many Lists(树状数组 set)
题意 题目链接 Sol 直接做肯定不好搞(反正我不会。。) 直接开\(n\)个Pair类型的set,维护每个数的出现位置 每次在set中二分后暴力合并即可 然后就是树状数组的基本操作了 时间复杂度:\
attack
2018/12/21
4000
2017.5.26暴力赛解题报告
预计分数:T1:40AC+60TLE      T2:40AC+60TLE        T3:10AC+90TLE      总分=90 实际分数:T1:100AC+0TLE      T2:80AC+20TLE        T3:20AC+80TLE      总分=200 感想:数据水的一逼!! 题目实际难度:   T1:提高/提高+   T2:提高+   T3:提高+/省选- 我眼中的难度 T1:普及   T2:普及-   T3:入门难度 2039. 树的统计 ★★   输入文件:counttr
attack
2018/04/13
7260
推荐阅读
相关推荐
洛谷P3372 【模板】线段树 1(树状数组)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档