先来介绍一下线段树。

线段树是一个把线段,或者说一个区间储存在二叉树中。如图所示的就是一棵线段树,它维护一个区间的和。

蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这段区间的和。

比如说线段树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 线段树点修改的更多相关文章

  1. codevs 1080 线段树练习 CDQ分治

    codevs 1080 线段树练习 http://codevs.cn/problem/1080/  时间限制: 1 s  空间限制: 128000 KB   题目描述 Description 一行N个 ...

  2. codevs 1080 线段树练习--用树状数组做的

    1080 线段树练习  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态 ...

  3. Codevs 1080 线段树练习(CDQ分治)

    1080 线段树练习  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 一行N个方格,开始每个格子里都有 ...

  4. codevs——1080 线段树练习

    1080 线段树练习  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 一行N个方格,开始每个格子里都有 ...

  5. codevs 1080 线段树练习

    链接:http://codevs.cn/problem/1080/ 先用树状数组水一发,再用线段树水一发 树状数组代码:84ms #include<cstdio> #include< ...

  6. Codevs 1080 线段树联系

    题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或 ...

  7. codevs 1080 线段树练习(线段树)

    题目: 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x ...

  8. wikioi 1080 线段树练习 树状数组

    1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond       题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现 ...

  9. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

随机推荐

  1. ITTC数据挖掘系统(六)批量任务,数据查看器和自由文档

    这一次带来了一系列新特新,同时我们将会从商业智能的角度讨论软件的需求 一. 批量任务向导 一个常用的需求是完成处理多个任务,可能是同一个需求以不同的参数完成多次,这类似批量分析某一问题:或者是不同的需 ...

  2. Oracle 11.2.0.4 RAC安装最新PSU补丁

    环境:两节点RAC(RHEL 6.4 + GI 11.2.0.4 + Oracle 11.2.0.4) 需求:安装最新PSU补丁11.2.0.4.7 1.下载补丁和最新OPatch 2.检查数据库当前 ...

  3. 中文分词工具探析(一):ICTCLAS (NLPIR)

    1. 前言 ICTCLAS是张华平在2000年推出的中文分词系统,于2009年更名为NLPIR.ICTCLAS是中文分词界元老级工具了,作者开放出了free版本的源代码(1.0整理版本在此). 作者在 ...

  4. 从.NET和Java之争谈IT这个行业

    一.有些事情难以回头 开篇我得表名自己的立场:.NET JAVA同时使用者,但更加偏爱.NET.原因很简单 1.NET语言更具开放性,从开源协议和规范可以看出; 2.语言更具优势严谨; 3.开发工具V ...

  5. 未能加载文件或程序集“Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5”或它的某一个依赖项。系统找不到指定的文件。

    在创建ASP.NET MVC项目过程中发生了这个异常 未能加载文件或程序集"Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0 ...

  6. Aspose.Cells导出Excel(1)

    利用Aspose.Cells导出excel 注意的问题 1.DataTable的处理 2.进行编码,便于中文名文件下载 3.别忘了Aspose.Cells.dll(可以自己在网上搜索) public ...

  7. vs2015 已经支持开发asp .net core 1.0 rc2 程序了

    vs2015 已经支持开发asp .net core 1.0 rc2 程序了 http://mp.weixin.qq.com/s?__biz=MzI0MzM1ODczOQ==&mid=2247 ...

  8. 阅读微信支付demo收获

       1,公司现有系统有很多,存放重要接口的日志分布在不同的库,每个系统都有单独的日志采集表,日志采集模块:        ????         这些日志可以统一放到一个地方,通过一个组件提供出去 ...

  9. Java Servlet+Objective-c图上传 步骤详细

    一. Servlet 1.创建图片保存的路径 在项目的WebContent下创建一个上传图片的专属文件夹. 这个文件夹创建后,我们保存的图片就在该文件夹的真实路径下,但是在项目中是无法看到上传的图片的 ...

  10. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...