AcWing 1264. 动态求连续区间和(树状数组 || 线段树)

树状数组和线段树以前很少接触,特别是线段树,竞赛见到的次数还是不少的,今天就彻底搞明白一下。

首先是树状数组,时间O(logN),能解决的问题是快速求动态的前缀和,也就是动态改变数组的值以后求前缀和(单点修改,区间查询),树状数组解决的就这一类问题,不过解决起来代码量小,速度快;对比线段树,能解决的问题就很广泛了。

线段树相比较树状数组,能解决的问题不仅仅是前缀和的问题,什么最大值之类的都可以解决,但是代码相对麻烦一点。
在这里插入图片描述

模板题
Problem

这个是树状数组的模板函数

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(System.out);
    static int n, x, y, q;
    static int a[], c[];

    public static void main(String[] args) throws IOException {
        String s[] = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        q = Integer.parseInt(s[1]);
        a = new int[n + 1];
        c = new int[n + 1];
        s = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) a[i] = Integer.parseInt(s[i - 1]);
        for (int i = 1; i <= n; i++) add(i, a[i]);
        
        while (q-- > 0) {
            s = br.readLine().split(" ");
            int handle = Integer.parseInt(s[0]);
            int a = Integer.parseInt(s[1]);
            int b = Integer.parseInt(s[2]);

            if (handle == 1) add(a, b);
            else pw.println(Sum(b) - Sum(a - 1));
        }

        pw.flush();
        pw.close();
        br.close();
    }

    public static void add(int x, int v) {
        for (int i = x; i <= n; i += lowbit(i))
            c[i] += v;
    }

    public static int lowbit(int x) {
        return x & -x;
    }

    public static int Sum(int x) {
        int res = 0;
        for (int i = x; i > 0; i -= lowbit(i)) res += c[i];
        return res;
    }

}

线段树解决这道题:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(System.out);
    static int N = 100010, n, m;
    static int w[] = new int[N];
    static Node node[] = new Node[N * 4];

    public static void main(String[] rags) throws IOException {
        String s[] = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        s = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) w[i] = Integer.parseInt(s[i - 1]);
        build(1, 1, n);

        for (int i = 1; i <= m; i++) {
            s = br.readLine().split(" ");
            int k = Integer.parseInt(s[0]);
            int a = Integer.parseInt(s[1]);
            int b = Integer.parseInt(s[2]);
            if (k == 0) pw.println(query(1, a, b));
            else modify(1, a, b);
        }
        pw.flush();
        pw.close();
        br.close();
    }

    private static void modify(int u, int x, int v) {
        if (node[u].getL() == node[u].getR()) node[u].setSum(node[u].getSum() + v);
        else {
            int mid = node[u].getL() + node[u].getR() >> 1;
            if (x <= mid) modify(u << 1, x, v);
            else modify(u << 1 | 1, x, v);
            pushup(u);
        }
    }

    private static int query(int u, int l, int r) {
        if (node[u].getL() >= l && node[u].getR() <= r) return node[u].getSum();
        int mid = node[u].getL() + node[u].getR() >> 1;
        int sum = 0;
        if (l <= mid) sum = query(u << 1, l, r);
        if (r > mid) sum += query(u << 1 | 1, l, r);
        return sum;
    }

    public static void build(int u, int l, int r) {
        if (l == r) node[u] = new Node(l, r, w[r]);
        else {
            node[u] = new Node(l, r);
            int mid = l + r >> 1;
            build(u << 1, l, mid);
            build(u << 1 | 1, mid + 1, r);
            pushup(u);
        }
    }

    public static void pushup(int u) {
        node[u].setSum(node[u << 1].getSum() + node[u << 1 | 1].getSum());
    }
}

class Node {
    private int l, r;

    public void setL(int l) {
        this.l = l;
    }

    public void setR(int r) {
        this.r = r;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    private int sum;

    public int getL() {
        return l;
    }

    public int getR() {
        return r;
    }

    public int getSum() {
        return sum;
    }

    public Node(int l, int r, int sum) {
        this.l = l;
        this.r = r;
        this.sum = sum;
    }

    public Node(int l, int r) {
        this.l = l;
        this.r = r;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值