• 权值线段树 基础入门知识详解


    权值线段树

    • 学习权值线段树,首先要了解线段树是什么。如果不会的可以先学习一下。

    是什么

    • 权值线段树,顾名思义是一棵线段树。
    • 但它和普通线段树不同:
    • 线段树,每个节点用来维护一段区间的最大值或总和等。
    • 权值线段树,相当于一个桶,每个节点用来表示一个区间的数出现的次数

    为什么要用它

    • 我们可以用它来维护一段区间的数出现的次数,从它的定义上来看,它可以快速计算一段区间的数的出现次数。
    • 此外,它还有一个重要功能,在于它可以快速找到第 k k k大或第 k k k小值,下面会做详细解释。
      其实,它就是一个桶,桶能做到的它都可以用更快的速度去完成。

    基本操作

    添加

    • 和普通线段树类似,递归到叶子节点时给 f [ v ] + 1 f[v]+1 f[v]+1
    • 以下代码要添加的数是 x x x,也就是 x x x出现的次数 + 1 +1 +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 ] f[v] f[v]的值即为所求次数。
    • 以下代码要查询的数是 x x 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 ] [x,y] [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 k k大值出现在右子树中,则递归进右子树;否则说明此时的第 k k k大值在左子树中,则递归进左子树,注意:此时要将 k k k的值减去右子树的总和。
    • 为什么要减去?
    • 如果我们要找的是第 7 7 7大值,右子树总和为 4 4 4 7 − 4 = 3 7-4=3 74=3,说明在该节点的第 7 7 7大值在左子树中是第 3 3 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);
    		}
    	}
    

    总结

    • 权值线段树的基础知识就是这些了,相信你都学会了。
    • 希望你能够灵活变通,在今后的OI生涯中更上一层楼。
    • 如果你想学习进阶知识,可以看看【主席树】可持久化线段树
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    如何在github上部署自己的前端项目
    springboot2.0整合springsecurity前后端分离进行自定义权限控制
    SpringDataJPA在Entity中常用的注解浅析
    JAVA算法之高级排序
    非关系型数据库MongoDB入门
    JAVA数据结构之哈希表
    JAVA算法之递归
    JAVA算法之简单排序
    JAVA数据结构之二叉树
    JAVA数据结构之链表
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910121.html
Copyright © 2020-2023  润新知