Processing math: 100%

权值线段树

预备知识

学习权值线段树的预备知识,就是线段树,如果没有学过线段树,推荐先看完线段树,再回来看本文章

权值线段树

  • 顾名思义,权值线段树是一颗线段树,但是又和普通的线段树不一样
  • 线段树:每个节点用来维护一个区间的最大值或者总和,等等
  • 权值线段树:与桶排序具有一定的相似性,每个节点相当于一个桶,用来表示一个区间的数出现的次数

相关问题

  • 根据定义可以知道,我们可以用它快速计算一段区间的数的出现次数,或者是维护
  • 当然他还有一个极其有用的功能,快速查找区间的第k大值或第k小值
  • 这边的节点,与桶排序中的桶极其相似

相关操作

添加

  • 和普通线段树类似,递归到叶子节点时给f[v]+=1
  • 以下代码要添加的数是x,也就是x出现的次数+1;
void add(int l, int r, int v, int x)
{
	if (l == r) f[v]++;
	else
	{
		int mid = (l + r) / 2;
		if (x <= mid) add(l, mid, v * 2, x);
		else add(mid + 1, r, v * 2 + 1, x);
		f[v] = f[v * 2] + f[v * 2 + 1];
	}
}

查找一个数出现的次数

  • 递归到叶节点是,f[v]即为所求值
  • 下面为寻找数x的出现次数的代码
int find(int l, int r, int v, int x)
{
	if (l == r) return f[v];
	else
	{
		int mid = (l + r) / 2;
		if (x <= mid) return find(l, mid, v * 2, x); 
		else return find(mid + 1, r, v * 2 + 1, x);
	}
}

查询一段区间的数的出现次数

  • 与线段树查询同理,不断的二分递归
  • 以下的代码为查询区间[x,y]出现的次数
int find(int l, int r, int v, int x, int y)
{
	if (l == x && r == y) return f[v];
	else
	{
		int mid = (l + r) / 2;
		if (y <= mid) return find(l, mid, v * 2, x, y);
		else if (x > mid) return find(mid + 1, r, v * 2 + 1, x, y);
		else return find(l, mid, v * 2, x, mid) + find(mid + 1, r, v * 2 + 1, mid + 1, y);
	}
}

查询所有数的第k大值

  • 还是先温故那句话:每个节点都是一个桶!这句话很重要
  • 这是权值线段树的核心,思想如下:
  • 到每个节点时,如果右子树的总和大于等于k,说明第k大值出现在右子树中,则递归进右子树;否则说明此时的第k大值在左子树中,则递归进左子树,注意:此时要将k的值减去右子树的总和。
  • 为什么要减去?
  • 假设我们要寻找的是第7大的值,右子树的总和为4,74=3,那么说明第7大值在左子树中是第3大值
  • 最后递归到只有一个数时,那个数就是答案
int kth(int l, int r, int v, int k)
{
	if (l == r) return l;
	else
	{
		int mid = (l + r) / 2, s1 = f[v * 2], s2 = f[v * 2 + 1];
		if (k <= s2) return kth(mid + 1, r, v * 2 + 1, k); 
		else return kth(l, mid, v * 2, k - s2);
	}
}

总结

  • 这些就是权值线段树的基本应用了
  • 掌握这些之后你就可以进一步学习主席树了
posted @   幽灵轩  阅读(144)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
阅读排行:
· 2025成都.NET开发者Connect圆满结束
· 后端思维之高并发处理方案
· 千万级大表的优化技巧
· 在 VS Code 中,一键安装 MCP Server!
· 10年+ .NET Coder 心语 ── 继承的思维:从思维模式到架构设计的深度解析
点击右上角即可分享
微信分享提示