P3374 【模板】树状数组 1(线段树)
【模板】树状数组 1
题目描述
如题,已知一个数列,你需要进行下面两种操作:
将某一个数加上
x求出某区间每一个数的和
输入格式
第一行包含两个正整数 n,m ,分别表示该数列数字的个数和操作的总个数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 m 行每行包含 3 个整数,表示一个操作,具体如下:
1 x k含义:将第x个数加上k2 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 的任意子区间(包括长度为 1 和 n 的子区间)和均在 [-2^{31}, 2^{31}) 范围内。
样例说明:

故输出结果14、16
思路:树状数组?线段树?
三步走!!!
建树
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];
}
修改数据
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);如果是在右子树就往右边找 }
计算答案
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(线段树)的更多相关文章
- st表、树状数组与线段树 笔记与思路整理
已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...
- bzoj3196 二逼平衡树 树状数组套线段树
题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...
- 2019南昌网络赛 I. Yukino With Subinterval 树状数组套线段树
I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- POJ 1195 Mobile phones (二维树状数组或线段树)
偶然发现这题还没A掉............速速解决了............. 树状数组和线段树比较下,线段树是在是太冗余了,以后能用树状数组还是尽量用......... #include < ...
- 【BZOJ3196】二逼平衡树(树状数组,线段树)
[BZOJ3196]二逼平衡树(树状数组,线段树) 题面 BZOJ题面 题解 如果不存在区间修改操作: 搞一个权值线段树 区间第K大--->直接在线段树上二分 某个数第几大--->查询一下 ...
- 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[ ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
随机推荐
- [转帖]Prometheus-使用python开发exporter
exporter有很多,但想要特定需求的话,还需自行开发.在这里使用python写一个exporter,用于监控/root下的目录数量. 开发exporter需要使用prometheus_client ...
- Prometheus+alertmanager实现告警的简单验证
Prometheus+alertmanager实现告警的简单验证 背景 学习源自: http://www.mydlq.club/article/126/ 上午没搞定, 中午睡不着,继续学习处理. 发现 ...
- [转帖]Elasticsearch-索引性能调优
1:设置合理的索引分片数和副本数 索引分片数建议设置为集群节点的整数倍,初始数据导入时副本数设置为 0,生产环境副本数建议设置为 1(设置 1 个副本,集群任意 1 个节点宕机数据不会丢失:设置更多副 ...
- Gin 框架之用户密码加密
目录 一.引入 二.密码加密位置 三.如何加密 四.bcrypt 库加密 4.1 介绍 4.2 优点: 4.3 使用 五.小黄书密码加密实践 一.引入 Gin是一个用Go语言编写的Web框架,而用户密 ...
- Gin 项目引入热加载
目录 一.什么是热加载 二.Air 2.1 介绍 2.2 特性 特性: 2.3 相关文档 2.4 安装 推荐使用 install.sh 使用 go install 2.5 配置环境变量 2.6 使用 ...
- Prompt实战优化
1.概述 在深度学习领域,Prompt(提示语)被广泛应用于自然语言处理任务中,如文本生成.机器翻译和问答系统等.Prompt的设计对模型的性能和生成结果有着重要的影响,因此在实际应用中合理而有效地利 ...
- [2] HEVD 学习笔记:栈溢出漏洞训练
2. HEVD 栈溢出漏洞训练 2.1 漏洞原理 当函数退出的时候,会将保存在栈中的返回地址取出,跳转到该地址继续执行,以此来执行函数调用以后的程序.而如果用户的输入没有得到控制,覆盖掉了这个返回 ...
- Unity2019使用Android Studio 4出安卓包
前言 在我所经历的项目组中有这几种方法来生成APK 直接在Unity生成APK,可以接入SDK 使用Unity导出Android Studio工程手动生成APK 使用Unity导出Android St ...
- TienChin 渠道管理-查看渠道接口
自定义 hasPermission 校验规则 自定义一个 Spring Security hasPermission 校验规则: 在 tienchin-framework 模块当中进行自定义,新建 C ...
- 通过docker-compose搭建mongo的replica set高可用
通过docker-compose搭建mongo的replica set高可用 前言 备份数据 备份数据到本地 数据恢复 集群搭建 生成keyFile 创建yml文件 初始化副本集 增加副本集 将节点初 ...