codevs 1080 线段树点修改
先来介绍一下线段树。
线段树是一个把线段,或者说一个区间储存在二叉树中。如图所示的就是一棵线段树,它维护一个区间的和。


蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这段区间的和。
比如说线段树1号节点表示[1,5]区间,它的值是13,也就是原数组1号位到5号位所有数字加起来的和。
不难发现线段树的下标有这样的性质:
1. 设一个节点的下号是o,那么它的左子树是o*2,右子树是o*2+1。
2. 线段树的大小是原数组的大小*2-1。
3. 线段树叶节点表示区间的长度为1,也就是一个数字,此时区间的左边界=区间的右边界。
但是我们实际使用的时候,线段树是用一个长度为原数组大小4倍的数组储存的,因为方便处理,防止访问叶节点时下标越界。
它支持几种操作:
1. 修改一个点的值
2. 将一个区间加上或减去某个数
3. 查询一个区间的和(乘积也可以),最大/最小值
4. 将一个区间值改变成某个大于0的数
以上时间复杂度都是logn。
建立线段树:
这里我采用递归的方式。在函数内设3个参数,这个线段树节点的下标o,它表示的左区间L,又区间R。从根节点开始递归,如果L=R,就是走到了叶节点(根据性质3),那么该点就是原数组第L(或R)位的值,否则分成两个区间,递归它的左右子树。
代码如下:
void init(int o,int L,int R)
{
if(L==R) sumv[o]=A[L]; //A[]是原数组,sumv[]是线段树数组
else
{
int M=(L+R)/;
init(o*,L,M);
init(o*+,M+,R);
sumv[o]=sumv[o*]+sumv[o*+];
}
}
这里的sumv是求和线段树数组,我以这个为例。当然如果是维护区间最大/最小,那么第9行的代码应该是左右子树的最大/最小值。
调用:
init(1,1,n);
// 1,n是总区间。
点修改:
与建树的过程类似,从根节点开始,一直递归到叶节点,然后直接修改,完成之后,更新sumv值就可以了。
如果把修改原数组p号位的值修改为v。
代码:
int p,v; void update(int o,int L,int R)
{
if(L==R) sumv[o]=v;
else
{
int M=(L+R)/;
if(p<=M) update(o*,L,M); else update(o*+,M+,R);
sumv[o]=sumv[o*]+sumv[o*+];
}
}
调用:
先把p,和v赋值好,然后直接调用即可
p=x,v=y;//x,y是你要赋的值
update(1,1,n);
查询区间的和:
还是与上面类似。从根节点开始递归。如果这一层的区间[L,R]包含于要求的区间[y1,y2],那么就把这一层的值累加,否则就访问它的子树,把这个区间一份为二。
如果它的子树表示的区间与要求的区间有交集,就说明有需要访问,否则就不用。
代码:
int y1,y2,ans;
void query(int o,int L,int R)
{
if(y1<=L && R<=y2) ans+=sumv[o];
else
{
int M=(L+R)/;
if(y1<=M) query(o*,L,M);
if(y2>M) query(o*+,M+,R);
}
}
调用:
把要查找的区间y1,y2赋值好,并把存储答案的ans清0,,再调用即可
y1=x,y2=y,ans=0;//注意ans一定要初始化,最后查出来的答案是保存在ans里面的。
query(1,1,n);
点修改的说明就到此。
测试的题目:codevs 1080 线段树练习
链接:http://codevs.cn/problem/1080/
附代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=; int A[maxn],sumv[maxn*],n,m; void init(int o,int L,int R)
{
if(L==R) sumv[o]=A[L];
else
{
int M=(L+R)/;
init(o*,L,M);
init(o*+,M+,R);
sumv[o]=sumv[o*]+sumv[o*+];
}
} int p,v;
void update(int o,int L,int R)
{
if(L==R) sumv[o]=v;
else
{
int M=(L+R)/;
if(p<=M) update(o*,L,M); else update(o*+,M+,R);
sumv[o]=sumv[o*]+sumv[o*+];
}
} int y1,y2,ans;
void query(int o,int L,int R)
{
if(y1<=L && R<=y2) ans+=sumv[o];
else
{
int M=(L+R)/;
if(y1<=M) query(o*,L,M);
if(y2>M) query(o*+,M+,R);
}
} int main()
{
cin>>n;
for(int i=;i<=n;i++) cin>>A[i];
init(,,n);
cin>>m;
for(int i=,k,x,y;i<=m;i++)
{
cin>>k>>x>>y;
if(k==)
{
p=x,v=A[p]+y;
A[p]=v;
update(,,n);
}
else
{
y1=x,y2=y,ans=;
query(,,n);
cout<<ans<<endl;
}
}
return ;
}
codevs 1080 线段树点修改的更多相关文章
- codevs 1080 线段树练习 CDQ分治
codevs 1080 线段树练习 http://codevs.cn/problem/1080/ 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 一行N个 ...
- codevs 1080 线段树练习--用树状数组做的
1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态 ...
- Codevs 1080 线段树练习(CDQ分治)
1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 一行N个方格,开始每个格子里都有 ...
- codevs——1080 线段树练习
1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 一行N个方格,开始每个格子里都有 ...
- codevs 1080 线段树练习
链接:http://codevs.cn/problem/1080/ 先用树状数组水一发,再用线段树水一发 树状数组代码:84ms #include<cstdio> #include< ...
- Codevs 1080 线段树联系
题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或 ...
- codevs 1080 线段树练习(线段树)
题目: 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x ...
- wikioi 1080 线段树练习 树状数组
1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
随机推荐
- 用SignalR 2.0开发客服系统[系列3:实现点对点通讯]
前言 交流群:195866844 目录: 用SignalR 2.0开发客服系统[系列1:实现群发通讯] 用SignalR 2.0开发客服系统[系列2:实现聊天室] 真的很感谢大家的支持,今天发表系列3 ...
- 异步编程系列第01章 Async异步编程简介
p { display: block; margin: 3px 0 0 0; } --> 2016.10.11补充 三个月过去了,回头来看,我不得不承认这是一系列失败的翻译.过段时间,我将重新翻 ...
- java访问修饰符
了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...
- linux grep命令
linux grep命令1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expressio ...
- yii2的权限管理系统RBAC简单介绍
这里有几个概念 权限: 指用户是否可以执行哪些操作,如:编辑.发布.查看回帖 角色 比如:VIP用户组, 高级会员组,中级会员组,初级会员组 VIP用户组:发帖.回帖.删帖.浏览权限 高级会员组:发帖 ...
- SQLSERVER截取字符串
) SET @Name = '\EXAM\061023478874' DECLARE @Position INT --sql first indexof SET @Position = CHARIND ...
- 【JS基础】DOM操作
appendChild() //向节点添加最后一个子节点 createElement() //创建元素节点 createTextNode() //创建文本节点,字符串值
- javascript 练习示例(一)
confirm 点确定返回true,点取消返回false prompt 点确定返回用户输入的字符串,点取消返回null 判断奇偶性 var isOdd = prompt('请输入你得的数字'); if ...
- ES5概述(ECMAScript262/5.1)
ES5概述(ECMAScript262/5.1) 本文参考:ES5概述 ECMAScript 是基于对象的: 基本语言和宿主设施都由对象提供,ECMAScript 程序是一组可通信的对象.ECMASc ...
- Jquery更改table中的内容(一)
css部分: .tab{ border:solid 1px #00aaee; text-align: left; margin:20px;}.tab tr{ border-top: solid 1px ...