线段树模版代码,代码中有详细注释,这个是区间和以及区间最值维护的综合版本。
实际使用时选择其中部分功能使用即可。另附代码如下:
package m5d15;
import java.io.BufferedInputStream;
import java.util.Scanner;
//同时维护区间和以及区间最大值,区间最小值与区间最大值同理
public class 线段树 {
//封装树节点
static class Node{
int l,r;//左右边界
int lazy;//懒标记
int sum;//区间和
int maxt;//最大值
//调试用的,实际使用时可以删除
@Override
public String toString() {
return "Node{" +
"l=" + l +
", r=" + r +
", lazy=" + lazy +
", sum=" + sum +
", maxt=" + maxt +
'}';
}
}
static Node[] tree = null;
static int val[] = null;
public static void main(String[] args) {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
int m = sc.nextInt();
val = new int[n+1];
for(int i=1;i<=n;i++){
val[i] = sc.nextInt();
}
tree = new Node[4*n+1];
buildTree(1,1,n);
for(int i=1;i<=m;i++){
int p = sc.nextInt();
int l = sc.nextInt();
int r = sc.nextInt();
//单点修改
if(p==1){
int val = sc.nextInt();
update(1,l,r,val);
} else if(p==2) {//求区间和
System.out.println(query(1,l,r).sum);
}
else if(p==3){//求区间最大值
System.out.println(query(1,l,r).maxt);
}else{//区间修改
int val = sc.nextInt();
update(1,l,r,val);
}
}
}
//建树
public static void buildTree(int x,int l,int r){
tree[x] = new Node();
tree[x].l = l;
tree[x].r = r;
if(l==r) {
tree[x].sum = val[l];
tree[x].maxt = val[l];
return ;
}
int mid = (l+r)>>1;
buildTree(x<<1,l,mid);
buildTree(x<<1|1,mid+1,r);
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
tree[x].maxt = Math.max(tree[x<<1].maxt,tree[x<<1|1].maxt);
}
//单点修改,值加val
public static void update(int x,int r,int val){
if(tree[x].l==tree[x].r&&tree[x].r==r){
tree[x].sum += val;
tree[x].maxt += val;
return;
}
int mid = (tree[x].l+tree[x].r)>>1;
if(r<=mid) update(x<<1,r,val);
else update(x<<1|1,r,val);
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
tree[x].maxt = Math.max(tree[x<<1].maxt,tree[x<<1|1].maxt);
}
//下传懒标记
public static void pushdown(int k){
//左儿子
tree[k<<1].lazy+=tree[k].lazy;
tree[k<<1].sum+=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].lazy;
tree[k<<1].maxt+=tree[k].lazy;
//右儿子
tree[k<<1|1].lazy+=tree[k].lazy;
tree[k<<1|1].sum+=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].lazy;
tree[k<<1|1].maxt+=tree[k].lazy;
//清除自己的标记
tree[k].lazy = 0;
}
//区间修改,区间内的值全部增加val
public static void update(int x,int l,int r,int val){
if(tree[x].l>=l&&tree[x].r<=r){
//更新值并进行懒标记
tree[x].sum+=(tree[x].r-tree[x].l+1)*val;
tree[x].maxt +=val;
tree[x].lazy +=val;
return;
}
if(tree[x].lazy!=0){
pushdown(x);
}
int mid = (tree[x].r+tree[x].l)>>1;
if(l<=mid) update(x<<1,l,r,val);
if(r>mid) update(x<<1|1,l,r,val);
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
tree[x].maxt = Math.max(tree[x<<1].maxt,tree[x<<1|1].maxt);
}
//区间查询,查询区间l到r的和以及最大值
public static Node query(int x,int l,int r){
if(tree[x].l>=l&&tree[x].r<=r){
return tree[x];
}
if(tree[x].lazy!=0){
pushdown(x);
}
int mid = (tree[x].l+tree[x].r)>>1;
Node node1=new Node();
Node node2=new Node();
if(l<=mid) node1 = query(x<<1,l,r);
if(r>mid) node2 = query(x<<1|1,l,r);
Node result = new Node();
result.sum = node1.sum+node2.sum;
result.maxt = Math.max(node1.maxt,node2.maxt);
return result;
}
}