数据结构-线段树

本文详细介绍了线段树的基本概念、图示例以及在Java中的应用,包括建树、修改、查询等操作,以小球与盒子问题为例,展示了如何使用线段树解决区间问题。
摘要由CSDN通过智能技术生成

📑前言

本文主要是【线段树】——线段树简单使用的文章,如果有什么需要改进的地方还请大佬指出⛺️

🎬作者简介:大家好,我是听风与他🥇
☁️博客首页:CSDN主页听风与他
🌄每日一句:狠狠沉淀,顶峰相见

[1-9]线段树图示

在这里插入图片描述

例题

1208.小球与盒子

package 难点攻克;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
/**
 * 线段树一般需要四个函数,build(root,l,n)建树函数,modify(root,x,k)修改函数
 * query(root,l,r)查询函数,pushup(root)更新函数
 * 单点修改:修改某个点的值,区间查询,查询某个区间内的值(min,max,sum)
 * 线段树比树状数组更强大
 *
 */
public class 小球与盒子 {
	static class node{
		int l,r;
		long v;
	}
	
	static node tree[];

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		sc.nextToken();
		int n = (int)sc.nval;
		sc.nextToken();
		int m = (int)sc.nval;
		tree = new node[n*4];
		build(1, 1, n);//建树
		while(m-->0) {
			sc.nextToken();
			int op = (int)sc.nval;
			sc.nextToken();
			int x = (int)sc.nval;
			sc.nextToken();
			int y = (int)sc.nval;
			if (op==1) {
				modify(1, x, y);//单点修改,单点修改时是x加上y
			}else {
				System.out.println(query(1, x, y));//区间查询
			}
		}
	}
	//建树函数
	public static void build(int u,int l,int r) {
		tree[u] = new node();//申请空间
		if (l == r) {//叶子节点
			tree[u].l=l;
			tree[u].r=r;
		}else {
			tree[u].l=l;
			tree[u].r=r;
			int mid = (l+r)/2;
			build(2*u, l, mid);//递归左节点,建立左子树
			build(2*u+1, mid + 1, r);//递归右节点,建立右子树
		}
	}
	
	public static long query(int u,int l,int r) {
		if(l <= tree[u].l && r>=tree[u].r) {
			return tree[u].v;
		}
		long res = 0;
		int mid = (tree[u].l + tree[u].r) / 2;
		if(l <= mid) {
			//往左边走,往右边走
			res = query(u*2, l, r);
		}
		if(r > mid) {
			res += query(u*2+1, l, r);
		}
		return res;
	}
	
	public static void modify(int u,int x,long k) {
		if(tree[u].l == tree[u].r) {
			tree[u].v += k;
		}else {
			int mid = (tree[u].l+tree[u].r)/2;
			//遍历左右子树,进行单点修改的更新
			if(x<=mid) {
				modify(u*2, x, k);
			}else {
				modify(u*2+1, x, k);
			}
			push(u);//更新u
		}
	}
	
	public static void push(int u) {
		tree[u].v = tree[u*2].v + tree[u*2+1].v;
	}

}

📑文章末尾

在这里插入图片描述

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听风与他

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值