数算实习 k-th number 线段树

本文介绍了一种解决数列中快速查询第K小数的高效算法,通过离散化和二分查找优化查询过程,适用于大规模数据集的查询需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

k-th number

给定数列a1,a2…an,各不相同。要进行m次查询,每次查询 a[L…R] 中第k小的数是什么 (1 <= n <= 100 000, 1 <= m <= 5 000) abs(ai) <= 10^9

样例输入
7 3 //7个数,3次查询
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
样例输出
5
6
3

#include <iostream>
#include <algorithm>
using namespace std;

int Array[100002];            //Array记录原始数组
int order[100002];            //order记录数组中每个元素对应的编号(从小到大)   离散化
int sortA[100002];            //sortA用来对数组排序并记录
int p;

struct tree
{
	int* store;
	int len;
	int l;
	int r;
	tree* left;
	tree* right;
};
void buildtree(tree* root, int L, int R)          
//将order数组第L到第R个元素,并将其排序后放入store数组中,方便之后用upper_bound函数进行二分查找
{
	root->len = R - L + 1;
	root->l = L;
	root->r = R;
	root->store = new int[root->len + 10];
	for (int i = 1; i <= root->len; i++)
	{
		root->store[i] = order[L + i - 1];
	}
	sort(root->store, root->store + root->len + 1);        //对store数组进行处理
	root->left = new tree;
	root->right = new tree;
	if (L == R)                        //分解到了最底层
		return;
	int mid = (L + R) / 2;
	buildtree(root->left, L, mid);
	buildtree(root->right, mid + 1, R);
}
void quary(tree* root, int L, int R, int mid)
{
	if (L == root->l&&R == root->r)
	{
		p += upper_bound(root->store + 1, root->store + root->len + 1, mid) - (root->store + 1);
		//store数组已经排序,看这个子结点中比mid小或相等的元素有多少
		return;
	}
	else
	{
		int Mid = (root->l + root->r) / 2;
		if (R <= Mid)
			quary(root->left, L, R, mid);
		else if (L >= Mid + 1)
			quary(root->right, L, R, mid);
		else
		{
			quary(root->left, L, Mid, mid);
			quary(root->right, Mid + 1, R, mid);
		}
	}
}

int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> Array[i];
		sortA[i] = Array[i];
	}
	sort(sortA + 1, sortA + n + 1);
	for (int i = 1; i <= n; i++)
	{
		order[i] = lower_bound(sortA + 1, sortA + 1 + n, Array[i]) - sortA;
	}
	tree* root = new tree;
	buildtree(root, 1, n);
	while (m--)
	{
		int l, r;
		int k;
		cin >> l >> r >> k;
		int tl = 1;
		int tr = n;
		if (l == r)
		{
			printf("%d\n", Array[l]);
			continue;
		}
		int mid = (tl + tr) / 2;
		while (1)
		{
			p = 0;
			if (tl == tr)
			{
				printf("%d\n", sortA[tl]);
				break;
			}
			quary(root, l, r, mid);
			if (p >= k)
			{
				tr = mid;
				mid = (tl + mid) / 2;
			}
			else
			{
				tl = mid + 1;
				mid = (tr + mid) / 2;
			}
		}
	}

	return 0;
}

### 如何在 Python 中实现二叉搜索树节点的删除操作 以下是基于提供的引用内容以及专业知识,给出的一个完整的 Python 实现方案: #### 节点类定义 为了构建二叉搜索树 (Binary Search Tree, BST),首先需要定义一个 `Node` 类来表示单个节点。 ```python class Node: def __init__(self, key): self.left = None self.right = None self.val = key ``` #### 二叉搜索树类定义 接着,创建一个用于管理整棵树的类 `BinarySearchTree`。此部分参考了相关内容[^2]。 ```python class BinarySearchTree: def __init__(self): self.root = None ``` #### 插入方法 插入新节点的操作遵循标准的二叉搜索树规则:左子节点值小于父节点值,右子节点值大于父节点值。 ```python def insert(self, node, val): if not node: return Node(val) if val < node.val: node.left = self.insert(node.left, val) elif val > node.val: node.right = self.insert(node.right, val) return node ``` #### 查找最小值函数 删除过程中可能需要用到寻找某个节点的后继(即其右子树中最左侧的叶子),这部分可以单独封装成辅助函数。 ```python def find_min(self, node): current = node while(current.left is not None): current = current.left return current ``` #### 删除节点的核心逻辑 删除分为三种情况讨论: 1. **目标节点无任何子节点** —— 直接移除; 2. **目标节点只有一个子节点** —— 将该子节点提升至被删位置; 3. **目标节点有两个子节点** —— 找到右子树中的最小值替代当前节点,并递归地从原位置删除这个最小值节点。 具体代码如下所示: ```python def delete_node(self, root, key): if not root: return root # 如果键值小于根节点,则继续向左子树查找并执行删除动作 if key < root.val: root.left = self.delete_node(root.left, key) # 同理对于右侧的情况也是如此处理 elif(key > root.val): root.right = self.delete_node(root.right, key) else: # 当前节点正好是要删除的目标对象时进入下面分支判断 if root.left is None : temp = root.right root = None return temp elif root.right is None : temp = root.left root = None return temp # 若存在两个孩子结点的话就取右边最小子作为新的顶替者 temp = self.find_min(root.right) # 把那个找到的小孩赋给现在的root的位置上 root.val = temp.val # 接着再把原先那条路径上的重复元素去掉即可完成整体流程 root.right = self.delete_node(root.right , temp.val) return root ``` 以上就是整个删除过程的具体实现方式[^1]。 #### 测试用例 最后提供一段简单的测试脚本验证上述功能是否正常工作。 ```python if __name__ == "__main__": bst = BinarySearchTree() keys = [50, 30, 70, 20, 40, 60, 80] for key in keys: bst.root = bst.insert(bst.root, key) print("Inorder traversal of the constructed tree:") # Assume an inorder function exists here to display elements. print("\nDelete 20") bst.root = bst.delete_node(bst.root, 20) # Again assume a method prints updated structure after deletion. ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值