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:给区 ...
随机推荐
- 设计模式(十三):从“FQ”中来认识代理模式(Proxy Pattern)
我们知道Google早就被墙了,所以FQ才能访问Google呢,这个“FQ”的过程就是一个代理的过程.“代理模式”在之前的博客中不止一次的提及过,之前的委托回调就是代理模式的具体应用.今天我们就从“F ...
- php登录注册页面及加载
php注册界面 <h1>注册页面</h1> <form acti ...
- 【分布式】Zookeeper服务端启动
一.前言 前面已经了解了Zookeeper会话相关知识点,接着来学习Zookeeper服务端相关细节. 二.服务端 服务端整体架构如下 Zookeeper服务器的启动,大致可以分为以下五个步骤 1. ...
- 你真的会玩SQL吗?你所不知道的 数据聚合
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- [C1] 优化 C1FlexGrid 单元格边框
一 优化理由 如下图所示,如果按照 C1FlexGrid 自带的单元格边框设置,即对每个单元格的 CellStyle 的 BorderThickness 进行设置,会得到如下图的效果: 其中,明显可 ...
- EnumHelper.cs枚举助手(枚举描述信息多语言支持)C#
C#里面经常会用到枚举类型,枚举是值类型对象,如果你想用枚举类型的多属性特性,或者你想在MVC页面上通过简单的值类型转换,将某字段值所代表的含义转换为文字显示,这时候必须要将枚举扩展,是它支持文本描述 ...
- Backbone中的model和collection在做save或者create操作时, 如何选择用POST还是PUT方法 ?
Model和Collection和后台的WEB server进行数据同步非常方便, 都只需要在实行里面添加一url就可以了,backbone会在model进行save或者collection进行cre ...
- Sublime Text通过插件编译Sass为CSS及中文编译异常解决
虽然PostCSS才是未来,但是Sass成熟稳定,拥有一大波忠实的使用者,及开源项目,且最近Bootstrap 4 alpha也从Less转到Sass了.所以了解Sass还是非常有必要的. 基于快速开 ...
- 改变你代码习惯的ES6
最近读阮一峰老师的ES6标准入门,让我感觉到了ES6的强大之处,读书之余整理了一些笔记,因为边读边记录的,所以可能会比较杂乱. ECMAScript和Javascript的关系 1996年11月,Ja ...
- AccountName LoginName 变更
当AD中把AccountName改掉后,网站集不会自动同步LoginName,需要使用命令行Move-SPUser domain/A->domian/B /*2013 Claim 认证 必须加 ...