【模板】树状数组 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  • 将某一个数加上 x

  • 求出某区间每一个数的和

输入格式

第一行包含两个正整数 n,m ,分别表示该数列数字的个数和操作的总个数。

第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。

接下来 m 行每行包含 3 个整数,表示一个操作,具体如下:

  • 1 x k 含义:将第 x 个数加上 k

  • 2 x y 含义:输出区间 [x,y] 内每个数的和

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

样例 #1

样例输入 #1

5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4

样例输出 #1

14
16

提示

【数据范围】

对于 30% 的数据,1 ≤ n ≤ 8$1 ≤ m ≤ 10

对于 70% 的数据,1 ≤ n,m ≤ 10^4

对于 100% 的数据,1 ≤ n,m ≤ 5 * 10^5

数据保证对于任意时刻,a 的任意子区间(包括长度为 1n 的子区间)和均在 [-2^{31}, 2^{31}) 范围内。

样例说明:

故输出结果14、16

思路:树状数组?线段树?

三步走!!!

  1. 建树

    void buildtree(int k,int l,int r){
    if(l==r){//l==r时就是分到只剩一个了
    f[k]=a[l];//此时返回叶子结点数据(也就是原数据)
    return;
    }
    //以下三步,就是找左右儿子
    //这个过程与归并排序的递归过程类似可以去看一下
    //其中2k和2k+1代表的是当前结点的左右子结点(这一步不详细展开,可以自己画图尝试)
    int mid=(l+r)>>1;
    buildtree(2*k,l,mid);
    buildtree(2*k+1,mid+1,r); //父亲结点=儿子结点的和
    f[k]=f[2*k]+f[2*k+1];
    }
  2. 修改数据

    void add(int k,int l,int r,int x,int y){//k表示第几个结点,l、r表示区间,x表示第几个值要修改,y表示要使原值+y
    //因为每次找到的都是第x个元素的父亲结点的父亲的父亲……所以直接+y
    f[k]+=y;//包含结点x的值都需要+y
    if(l==r) return;当递归到l=r即为只有一个元素返回
    int mid=(l+r)>>1;
    if(x<=mid) add(2*k,l,mid,x,y);如果是在左子树就往左找
    else add(2*k+1,mid+1,r,x,y);如果是在右子树就往右边找 }
  3. 计算答案

    int calc(int k,int l,int r,int s,int t){//s、t表示要求的区间反围
    if(l==s && r==t)//如果区间缩小到包含原数据区间的子区间反围即返回
    return f[k];
    int mid=(l+r)>>1;
    if(t<=mid)
    return calc(2*k,l,mid,s,t);//如果当前要求的区间范围在左子树就往左边找
    else//在右子树或者部分在右子树
    if(s>mid)
    return calc(2*k+1,mid+1,r,s,t);//在右子树上
    else
    return calc(2*k,l,mid,s,mid)+calc(2*k+1,mid+1,r,mid+1,t);//部分在右子树
    }

tips:这个树状数组应该开多大?

开4n。参考证明连接:线段树需要开4倍区间大小的数组的原因_线段树数组一般开 n*4 的大小-CSDN博客

(本文章仅供学习交流如有侵权请私信立刻删除)

AC Code

// Problem:
// P3374 【模板】树状数组 1
//
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3374
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org) #include<iostream>
#include<algorithm>
//#include<cstdio> #define ll long long
#define endl '\n'
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>(b);i--)
#define N 2000100 //1e6+100
#define M 500010
using namespace std;
int f[N],a[M],n,m;
void buildtree(int k,int l,int r){
if(l==r){
f[k]=a[l];
return;
}
int mid=(l+r)>>1;
buildtree(2*k,l,mid);
buildtree(2*k+1,mid+1,r);
f[k]=f[2*k]+f[2*k+1];
}
void add(int k,int l,int r,int x,int y){
f[k]+=y;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) add(2*k,l,mid,x,y);
else add(2*k+1,mid+1,r,x,y);
}
int calc(int k,int l,int r,int s,int t){
if(l==s && r==t)
return f[k];
int mid=(l+r)>>1;
if(t<=mid)
return calc(2*k,l,mid,s,t);
else
if(s>mid)
return calc(2*k+1,mid+1,r,s,t);
else
return calc(2*k,l,mid,s,mid)+calc(2*k+1,mid+1,r,mid+1,t);
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
rep(i,1,n)
cin>>a[i];
buildtree(1,1,n);
int t,x,y;
while(m--){
cin>>t>>x>>y;
if(t==1)
add(1,1,n,x,y);
else cout<<calc(1,1,n,x,y)<<endl;;
}
return 0;
}

P3374 【模板】树状数组 1(线段树)的更多相关文章

  1. st表、树状数组与线段树 笔记与思路整理

    已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树

    I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...

  4. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  5. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  6. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  7. POJ 1195 Mobile phones (二维树状数组或线段树)

    偶然发现这题还没A掉............速速解决了............. 树状数组和线段树比较下,线段树是在是太冗余了,以后能用树状数组还是尽量用......... #include < ...

  8. 【BZOJ3196】二逼平衡树(树状数组,线段树)

    [BZOJ3196]二逼平衡树(树状数组,线段树) 题面 BZOJ题面 题解 如果不存在区间修改操作: 搞一个权值线段树 区间第K大--->直接在线段树上二分 某个数第几大--->查询一下 ...

  9. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

  10. P3157 [CQOI2011]动态逆序对(树状数组套线段树)

    P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...

随机推荐

  1. IPV6的简单学习与整理

    背景 大概2018年时曾经突击学习过一段时间IPV6 当时没太有写文档的习惯,导致这边没有成型的记录了. 今天又有项目要求使用IPV6, 想了想就将之前学习的部分 还有想继续学习提高的部分进行一下总结 ...

  2. Oracle表数量对数据泵备份恢复速度的影响情况

    Oracle表数量对数据泵备份恢复速度的影响情况 背景 随着公司产品交付后的时间越来越久. 数据库的备份恢复速度会越来越慢. 最开始一直认为是因为数据量导致的. 但是最近发现, 如果只是将数据库表的量 ...

  3. Redis如何批量删除指定前缀的key

    批量删除指定前缀的Key有两中方法,一种是借助 redis-cli,另一种是通过 SCAN 命令来遍历所有匹配前缀的 key,并使用 DEL 命令逐个删除它们. redis-cli 使用 Redis ...

  4. StackFrame和StackTrace在Unity和C#中的区别

    本文通过实际例子来看看StackFrame和StackTrace有什么区别,分别在.NET和Unity中测试. .NET环境 测试代码 using System; using System.Diagn ...

  5. go中的sync.pool源码剖析

    sync.pool sync.pool作用 使用 适用场景 案例 源码解读 GET pin pinSlow getSlow Put poolChain popHead pushHead pack/un ...

  6. MySQL【一】基本使用----超详细教学

    相关文章: win10下MySQL安装教程(MySql-8.0.26超级详细)_丨汀.的博客-CSDN博客 1.RDBMS(Relational Databases Management System ...

  7. Midjourney|文心一格prompt教程[技巧篇]:生成多样性、增加艺术风格、图片二次修改、渐进优化、权重、灯光设置等17个技巧等你来学

    Midjourney|文心一格prompt教程[技巧篇]:生成多样性.增加艺术风格.图片二次修改.渐进优化.权重.灯光设置等17个技巧等你来学 1.技巧一:临摹 我认为学习图片类的 prompt,跟学 ...

  8. tensorflow语法【tf.concat()详解】

    相关文章: [一]tensorflow安装.常用python镜像源.tensorflow 深度学习强化学习教学 [二]tensorflow调试报错.tensorflow 深度学习强化学习教学 [三]t ...

  9. LoopAndLoop【安卓逆向】

    LoopAndLoop(阿里CTF) 首先是通用步骤 解压附件后发现是APK文件,打开jeb进行反编译,反编译结果如下: 可以看到程序自定了几个check函数,并且调用了自定义库"lhm&q ...

  10. WinForm之ComboBox实现模糊查询

    ComboBox实现模糊查询 第一步:在Form_Load事件中绑定数据源 第二步:写一个方法,返回一个List<string>类型的集合来存储控件中的Items 第三步:在Form_Lo ...