蓝桥杯JAVA-13.线段树模板(JAVA实现)

蓝桥杯复习知识点汇总

目录

单点修改

import java.io.*;
import java.math.BigInteger;
import java.util.Scanner;


/**
 * @Author DragonOne
 * @Date 2021/12/5 21:27
 * @墨水记忆 www.tothefor.com
 */
public class Main {
    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);

    public static int maxd = 100000+7;

    public static int[] a = new int[maxd]; //原数组
    public static int[] tree = new int[maxd*4]; //树存储

    //初始化建树
    public static void build(int p,int l,int r){
        if(l==r){
            tree[p]=a[l];
            return ;
        }
        int mid = (r+l)/2; // 防止爆范围
        build(p*2,l,mid); //左子树
        build(p*2+1,mid+1,r); //右子树
        tree[p]=tree[p*2]+tree[p*2+1];
    }

    //将x位置的值加上num
    public static void update(int p,int l,int r,int x,int num){
        if(x>r||x<l) return ;
        if(l==r&&l==x){ //找到x位置
            tree[p] += num; //灵活变
            return ;
        }
        int mid = (r+l)/2;
        update(p*2,l,mid,x,num);
        update(p*2+1,mid+1,r,x,num);
        tree[p]=tree[p*2]+tree[p*2+1];
    }

    //查询区间和
    public static int query(int p,int l, int r ,int x, int y){
        if(x<=l&&r<=y) return tree[p];
        if(x>r||y<l) return 0;
        int mid = (r+l)/2;
        int sum = 0;
        sum+=query(p*2,l,mid,x,y);
        sum+=query(p*2+1,mid+1,r,x,y);
        return sum;
    }


    public static void main(String[] args) throws Exception {

        int n = nextInt();
        int m = nextInt();
        for(int i=1;i<=n;++i){
            a[i] = nextInt();
        }
        build(1,1,n); //注意此位置必须在a数组输入后
        for(int i=1;i<=m;++i){
            int a1 = nextInt();
            int a2 = nextInt();
            int a3 = nextInt();
            if(a1==1) update(1,1,n,a2,a3);
            else System.out.println(query(1,1,n,a2,a3));
        }

        closeAll();
    }

    public static void cinInit(){
        cin.wordChars('a', 'z');
        cin.wordChars('A', 'Z');
        cin.wordChars(128 + 32, 255);
        cin.whitespaceChars(0, ' ');
        cin.commentChar('/');
        cin.quoteChar('"');
        cin.quoteChar('\'');
        cin.parseNumbers(); //可单独使用来还原数字
    }

    public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }

}

测试数据:

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

结果

64

区间修改

import java.io.*;
import java.math.BigInteger;
import java.util.Scanner;


/**
 * @Author DragonOne
 * @Date 2021/12/5 21:27
 * @墨水记忆 www.tothefor.com
 */
public class Main {
    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);

    public static int maxd = 100000+7;

    public static int[] a = new int[maxd]; //原数组
    public static int[] tree = new int[maxd*4]; //树存储
    public static int[] lazy = new int[maxd*4]; //懒惰标记

    //初始化建树
    public static void build(int p,int l,int r){
        if(l==r){
            tree[p]=a[l];
            return ;
        }
        int mid = (r+l)/2; // 防止爆范围
        build(p*2,l,mid); //左子树
        build(p*2+1,mid+1,r); //右子树
        tree[p]=tree[p*2]+tree[p*2+1];
        lazy[p]=0;
    }
    public static void push_down(int p ,int l ,int r ){
        if(lazy[p]!=0){
            lazy[p*2] += lazy[p];
            lazy[p*2+1] += lazy[p];
            int mid = (r+l)/2;
            tree[p*2] += (mid-l+1) * lazy[p];
            tree[p*2+1] += (r-mid) * lazy[p];
            lazy[p]=0;
        }

    }

    //将区间(x,y)的值加上num
    public static void update(int p,int l,int r,int x,int y,int num){
        if(x>r||x<l) return ;
        if(x<=l&&r<=y){ //找到区间
            lazy[p] += num;
            tree[p] += (r-l+1)*num;
            return ;
        }
        push_down(p,l,r);
        int mid = (r+l)/2;
        update(p*2,l,mid,x,y,num);
        update(p*2+1,mid+1,r,x,y,num);
        tree[p]=tree[p*2]+tree[p*2+1];
    }

    //查询区间和
    public static int query(int p,int l, int r ,int x, int y){
        if(x<=l&&r<=y) return tree[p];
        if(x>r||y<l) return 0;
        push_down(p,l,r);
        int mid = (r+l)/2;
        int sum = 0;
        sum+=query(p*2,l,mid,x,y);
        sum+=query(p*2+1,mid+1,r,x,y);
//        tree[p]=tree[p*2]+tree[p*2+1];
        return sum;
    }


    public static void main(String[] args) throws Exception {

        int n = nextInt();
        int m = nextInt();
        for(int i=1;i<=n;++i) a[i] = nextInt();
        build(1,1,n);
        for(int i=1;i<=m;++i){
            int a1 = nextInt();
            if(a1==1) {
                int a2 = nextInt();
                int a3 = nextInt();
                System.out.println(query(1,1,n,a2,a3));
            }
            else {
                int a2 = nextInt();
                int a3 = nextInt();
                int a4 = nextInt();
                update(1,1,n,a2,a3,a4);
            }
        }

        closeAll();
    }

    public static void cinInit(){
        cin.wordChars('a', 'z');
        cin.wordChars('A', 'Z');
        cin.wordChars(128 + 32, 255);
        cin.whitespaceChars(0, ' ');
        cin.commentChar('/');
        cin.quoteChar('"');
        cin.quoteChar('\'');
        cin.parseNumbers(); //可单独使用来还原数字
    }

    public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }

}

测试数据:

5 3
1 2 3 4 5
1 1 5
2 1 5 -1
1 1 5

输出:

15
10

还有二维线段树。有机会再写吧。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值