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) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
随机推荐
- [转帖]TiDB系统调参实战经验
https://tidb.net/blog/c9466c40#TiDB%E7%B3%BB%E7%BB%9F%E8%B0%83%E5%8F%82%E5%AE%9E%E6%88%98%E7%BB%8F%E ...
- [转帖]浅析TiDB二阶段提交
https://cloud.tencent.com/developer/article/1608073 关键内容说明: TiDB 对于每个事务,会涉及改动的所有key中,选择出一个作为当前事务的Pri ...
- [转帖]Linux-find命令报错: missing argument to `-exec'
https://www.cnblogs.com/yeyuzhuanjia/p/17427143.html 报错提示:find: missing argument to `-exec' 今天写一个清理脚 ...
- [转帖]使用JAYDEBEAPI同时连接两个不同数据库(ORACLE+MYSQL)的问题
jaydebeapi 同时连接两种数据库 在使用jaydebeapi只连接一种数据库时,是没问题的,但是如果需要同时连接两种数据库,比如同时连接oracle和mysql 例如以下测试代码: imp ...
- [转帖]Linux 防火墙开放特定端口 (iptables)
查看状态: iptables -L -n 下面添加对特定端口开放的方法: 使用iptables开放如下端口 /sbin/iptables -I INPUT -p tcp --dport 8000 -j ...
- [转帖]Linux性能调优之内存负载调优的一些笔记
https://zhuanlan.zhihu.com/p/548770928 写在前面 整理一些Linux内存调优的笔记,分享给小伙伴 博文没有涉及的Demo,理论方法偏多,可以用作内存调优入门 博文 ...
- 数据结构与算法 第一章(48课时课程笔记)Data Structure and Algorithms
数据结构基础知识 数据(Data):是对信息的一种符号表示.在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称.数据元素(Data Element):是数据的基本单位,在计算机程序中 ...
- 大数据平台Bug Bash大扫除最佳实践
一.背景 随着越来越多的"新人"在日常工作以及大促备战中担当大任,我们发现仅了解自身系统业务已不能满足日常系统开发运维需求.为此,大数据平台部门组织了一次Bug Bash活动,既能 ...
- ARC150D - Removing Gacha (树上期望)
Link 题意: 给一棵 \(n\) 个节点的树,称一个点是好的,当且仅当它到根的路径上都是黑色(包括自己).每次在不好的节点中随机选一个把它涂成黑色(不管原来它是否是白的),直到所有点都是好的为止. ...
- css3文字阴影和盒子阴影
文字阴影 文字阴影的语法格式: text-shadow:水平向右的偏移值 向下的偏移值 迷糊度 阴影的颜色,水平向右的偏移值 向下的偏移值 迷糊度 阴影的颜色; 可以有多个阴影,但是在实际的项目中最多 ...