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) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
 
随机推荐
- 鲲鹏920上面 Docker 部署 clickhouse 的方式方法
			
鲲鹏920上面 Docker 部署 clickhouse 的方式方法 背景 最近有一套鲲鹏920的测试环境, 研发同事想纯Dcoker部署一套环境. 其中就包括了 Clickhouse 之前发现Cli ...
 - [转帖]Prometheus系列之Grafana 版本9.0.0 设置Email邮件报警实战
			
目录 1. 配置文件conf/defaults.ini修改 2. Grafana Web页面配置报警邮箱接收者 3. 创建Dashboard 4. 创建Alert的文件夹 5. 设置Notificat ...
 - [转帖]深入理解mysql-第六章 mysql存储引擎InnoDB的索引-B+树索引
			
一.引入索引 在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于我们并不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,因为要遍历所有的数据页,时间复杂度就是O(n ...
 - [转帖]jmeter无图形界面执行测试并生成报告
			
1.进入jmeter的安装目录,找到bin文件夹,进入这个文件执行以下命名 jmeter -n -t test\xxx.jmx -l test\cli0705.jtl -e -o test\resul ...
 - WorkStation的网络损耗
			
WorkStation的网络损耗 背景 对周六遇到的问题进行了一下深入思考. 发现虽然可以通过WorkStation的方式来进行Clients以及新命令的扩容. 但是Workstation的桥接网络模 ...
 - Docker搭建SvnServer
			
下载svn-server官方镜像 docker pull garethflowers/svn-server 运行svn-server容器 docker run -v /home/svn:/var/op ...
 - 我对computed的理解-以及computed的传参
			
computed 传参 <template> <div> <p>computed传参的写法:{{ who1Params('--我是传参的内容') }}</p& ...
 - 【验证码逆向专栏】最新某验三代滑块逆向分析,干掉所有的 w 参数!
			
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容.敏感网址.数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 本文章未经许 ...
 - [置顶] k8s,docker,微服务,监控
			
综合 第一篇:k8s服务A内部调用服务B的方式 第二篇:go-zero grpc 第一篇:grpc,protobuf安装 第二篇:grpc签发证书 第三篇:golang-grpc 第四篇:python ...
 - PLC检测
			
填空题1 填空A-E 程序图一 第一训练题的程序,一个是用常开触点,一个是用上升沿指令,建议选上升沿指令编程 程序二 程序图三 程序四 程序五