线段树--第k小数

【平衡树】第K小数

Time Limit:150000MS  Memory Limit:1655360K
Case Time Limit:15000MS

Description

  现在已有N个整数,你有以下三种操作: 
A 表示加入一个值为A的整数 
B 表示删除其中值为B的整数 
K 表示输出这些整数中第K小的数

Input

第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作 
第二行用空格隔开的N个整数 
接下来M行,每行表示一个操作

Output

若干行,一行一个整数,表示所求的第K小的数字

Sample Input

5 5 
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3

Sample Output

0
7

Hint

注意:如果有多个大小相同的数字,只把他们看做一个数字,如样例。 
若找不到第K小的数,输出0 
数据范围: 
0<=N<=2,000,000 
M<=1,000,000 
-1,000,000,000<=每个整数<=1,000,000,000

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
struct node{
	long long ls,rs,sum;
};
node tree[40000005];
long long n,m,tot=1,cnt=0;
long long dt=1;
bool flag;
void add(long long &p,long long l,long long r,long long k){
	if(k<l||r<k)return;
	long long mid=(l+r)>>1;
	if(l==r){
		if(p==0){
			p=++tot;
			if(dt==1){
				tree[p].sum+=dt;
				flag=true;
			}
			return;
		}
		else if(tree[p].sum==0){
			if(dt==1){
				tree[p].sum+=dt;
				flag=true;
			}
			return;
		}
		else if(tree[p].sum>=1){
			if(dt==-1){
				tree[p].sum+=dt;
				flag=true;
			}
			return;
		}
		else return;
	}
	else if(p==0){
		p=++tot;
	} 
	add(tree[p].ls,l,mid,k);
	add(tree[p].rs,mid+1,r,k);
	if(flag)tree[p].sum+=dt;
}
long long query(long long p,long long l,long long r,long long k){
	long long mid=(l+r)>>1;
	if(l==r)return l;
	else if(tree[tree[p].ls].sum>=k)return query(tree[p].ls,l,mid,k);
	else return query(tree[p].rs,mid+1,r,k-tree[tree[p].ls].sum);
}
int main(){
	long long i,j,k;
	long long temp=1;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		long long a;
		scanf("%I64d",&a);
		a+=1000000001;
		flag=false;
		add(temp,1,2000000001,a);
		if(flag)cnt++;
	}
	while(m--){
		long long x,a;
		scanf("%I64d%I64d",&x,&a);
		if(x==1){
			flag=false;
			dt=1;
			a+=1000000001;
			add(temp,1,2000000001,a);
			if(flag)cnt++;
		}
		if(x==2){
			flag=false;
			dt=-1;
			a+=1000000001;
			add(temp,1,2000000001,a);
			if(flag)cnt--;
		}
		if(x==3){
			if(a>cnt)printf("0\n");
			else printf("%I64d\n",query(temp,1,2000000001,a)-1000000001);
		}
	}
	//printf("%I64d",cnt);
}


以下是使用 Python 基于 AVL 树(一种平衡二叉搜索树)实现插入数据和输出并删除第 K 小数据操作的算法代码: ```python # 定义 AVL 树节点类 class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right self.height = 1 self.size = 1 # 记录以该节点为根的子树的节点数量 # 定义 AVL 树类 class AVLTree: def __init__(self): self.root = None # 获取节点的高度 def get_height(self, node): if not node: return 0 return node.height # 获取节点的子树节点数量 def get_size(self, node): if not node: return 0 return node.size # 更新节点的高度和子树节点数量 def update_height_size(self, node): node.height = 1 + max(self.get_height(node.left), self.get_height(node.right)) node.size = 1 + self.get_size(node.left) + self.get_size(node.right) # 右旋操作 def right_rotate(self, y): x = y.left T2 = x.right x.right = y y.left = T2 self.update_height_size(y) self.update_height_size(x) return x # 左旋操作 def left_rotate(self, x): y = x.right T2 = y.left y.left = x x.right = T2 self.update_height_size(x) self.update_height_size(y) return y # 获取节点的平衡因子 def get_balance(self, node): if not node: return 0 return self.get_height(node.left) - self.get_height(node.right) # 插入节点 def insert(self, node, key): if not node: return TreeNode(key) elif key < node.val: node.left = self.insert(node.left, key) else: node.right = self.insert(node.right, key) self.update_height_size(node) balance = self.get_balance(node) # 左左情况 if balance > 1 and key < node.left.val: return self.right_rotate(node) # 右右情况 if balance < -1 and key > node.right.val: return self.left_rotate(node) # 左右情况 if balance > 1 and key > node.left.val: node.left = self.left_rotate(node.left) return self.right_rotate(node) # 右左情况 if balance < -1 and key < node.right.val: node.right = self.right_rotate(node.right) return self.left_rotate(node) return node # 查找第 K 小的节点并删除 def kth_smallest_and_delete(self, node, k): if not node: return None, -1 left_size = self.get_size(node.left) if k <= left_size: new_left, result = self.kth_smallest_and_delete(node.left, k) node.left = new_left elif k == left_size + 1: result = node.val if not node.left: return node.right, result elif not node.right: return node.left, result temp = self.get_min_value_node(node.right) node.val = temp.val node.right, _ = self.kth_smallest_and_delete(node.right, 1) else: new_right, result = self.kth_smallest_and_delete(node.right, k - left_size - 1) node.right = new_right self.update_height_size(node) balance = self.get_balance(node) # 左左情况 if balance > 1 and self.get_balance(node.left) >= 0: return self.right_rotate(node), result # 右右情况 if balance < -1 and self.get_balance(node.right) <= 0: return self.left_rotate(node), result # 左右情况 if balance > 1 and self.get_balance(node.left) < 0: node.left = self.left_rotate(node.left) return self.right_rotate(node), result # 右左情况 if balance < -1 and self.get_balance(node.right) > 0: node.right = self.right_rotate(node.right) return self.left_rotate(node), result return node, result # 获取最小节点 def get_min_value_node(self, node): current = node while current.left is not None: current = current.left return current # 插入值 def insert_value(self, key): self.root = self.insert(self.root, key) # 输出并删除第 K 小的数据 def delete_kth_smallest(self, k): self.root, result = self.kth_smallest_and_delete(self.root, k) return result # 主函数处理输入输出 def process_operations(input_str): operations = list(map(int, input_str.split())) num_operations = operations[0] avl_tree = AVLTree() results = [] index = 1 while index < len(operations): op = operations[index] if op == 1: # 插入操作 value = operations[index + 1] avl_tree.insert_value(value) index += 2 elif op == 2: # 输出并删除第 K 小的数据操作 k = operations[index + 1] result = avl_tree.delete_kth_smallest(k) results.append(result) index += 2 return results input_str = "8 1 1 1 2 1 3 1 4 1 5 2 2 2 2 2 6" output = process_operations(input_str) print(" ".join(map(str, output))) ``` ### 代码解释: 1. **TreeNode 类**:定义了 AVL 树的节点结构,包含节点值、左右子节点、高度和以该节点为根的子树的节点数量。 2. **AVLTree 类**:实现了 AVL 树的基本操作,包括插入节点、旋转操作(左旋、右旋)、获取平衡因子、查找并删除第 K 小的节点等。 3. **process_operations 函数**:处理输入的操作序列,根据操作类型(插入或输出并删除第 K 小的数据)调用相应的方法,并记录结果。 ### 复杂度分析: - **时间复杂度**:插入操作和删除第 K 小的节点操作的时间复杂度均为 $O(log n)$,其中 $n$ 是树中节点的数量。 - **空间复杂度**:$O(n)$,主要用于存储 AVL 树的节点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值