📑前言
本文主要是【线段树】——线段树简单使用的文章,如果有什么需要改进的地方还请大佬指出⛺️
🎬作者简介:大家好,我是听风与他🥇
☁️博客首页:CSDN主页听风与他
🌄每日一句:狠狠沉淀,顶峰相见
目录
- 📑前言
- [1-9]线段树图示
- 例题
- 📑文章末尾
[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 stubStreamTokenizer 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;}}