IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 线段树 -> 正文阅读

[数据结构与算法]线段树

学习笔记四

线段树

数据结构在noi比赛中的重要性不言而喻,我们已经学了两个十分简洁有神奇的数据结构,现在我来看一个又长又好用的线段树。
首先我们要知道线段树可以干啥,区间之间的操作,单点查询,区间查询,区间修改什么的,记住有了线段树以后就不要在用O(n)的暴力搜索了。
建树。。。。
线段树的本质是一个二叉树,我们用递归的方法来建树,用回溯的方法来确定定值,只要到叶子结点赋值并且返回。代码如下:

void build(int l,int r,int o){
	if(l==r) {
		tree[o]=a[l];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,2*o);
	build(mid+1,r,2*o+1);
	tree[o]=tree[2*o]+tree[2*o+1];
}

单点查询。。。。
这个也很简单,如果该点在mid左就照左孩子,在右边就找右孩子,找到了就返回,这个比较无聊我们可以直接跳过它的代码。

单点修改。。。。
这个和单点查询差不多,不断的找左右孩子,就OK了,代码如下:

int dandian(int x,int k,int l,int r,int o){
	if(l==r&&r==x){
		tree[o]+=k;
		return;
	}
	int mid=(l+r)/2;
	if(mid>=x) dandian(x,k,l,mid,2*o);
	if(mid<x) dandian(x,k,mid+1,r,2*o+1); 
	tree[o]=tree[2*o]+tree[2*o+1];
}

区间修改。。。。
这里面我们就要用到线段树的精华,懒标记。假设我们找到的区间完全包含于要修改的区间里,那么我们就修改这个区间的值,并且我们要记得给他打上懒标记,并且返回,这里就体现了线段树的精髓,标记而不下推,在查询是再去更改。假如不完全包含,那么我们就看看左边有交集就找左边,右边有交集就找右边,等到完全包含再去修改并且打上懒标记。下推懒标记的pushdown也在下面。代码如下:

int lazy[40000]={0};
void pushdown(int l,int r,int o){
	if(lazy[o]!=0){
		lazy[2*o]+=lazy[o];
		lazy[2*o+1]+=lazy[o];
		tree[2*o]+=l*lazy[o];
		tree[2*o+1]+=r*lazy[o];
		lazy[o]=0;
	}
}

void change(int l,int r,int c,int d,int u,int o){//给c到d上的每一个数字加u 
	if(l>=c&&r<=d){
		tree[o]+=u*(l-r+1);
		lazy[o]+=u;
		return;
	}
	int mid=(l+r)/2;
	pushdown(mid-l+1,r-mid,o);
	if(mid>=c) change(l,mid,c,d,u,2*o);
	if(mid<d) change(mid+1,r,c,d,u,2*o+1);
	tree[o]=tree[2*o]+tree[2*o+1]; 
}

区间查询。。。。
还是和刚才一样如果完全包含就加上。如果完全不包含就返回0(这是一个保障和优化),之后我们一定要pushdown,给之前没干的事情一个补偿,之后如果左边包含就找左边,右边包含就找右边。代码如下:

void search(int l,int r,int c,int d,int o){
	if(l>=c&&r<=d){
		return tree[o];
	}
	int mid=(r+l)/2;
	pushdown(mid-l+1,r-mid,o);
	int ans=0;
	if(mid>=c) ans+=search(l,mid,c,d,2*o);
	if(mid<d) ans+=search(mid+1,r,c,d,2*o+1);
	return ans;	
}

这就是最基础的线段树了,像是什么主席树啦,什么根号线段树以后可能会讲一下下吧,那就下次见啦,下一次应该是哈夫曼树,用那个荷马史诗来直接进阶。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:27:49  更:2021-08-04 11:28:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 4:41:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码