[Rust刷题模板] 树状数组BIT

一、 算法&数据结构

1. 描述

PURQ的树状数组可以用来单点更新区间查询
  • 模板慢慢补充,更详细的可以看我的py版本。

2. 复杂度分析

  1. 查询query, O(log2n)
  2. 更新update,O(log2n)

3. 常见应用

4. 常用优化

二、 模板代码

1. 单点更新,区间询问求和(PURQ)

#[allow(unused)]
use std::collections::*;
use std::io::{BufRead, BufWriter, Write};
#[allow(unused)]
fn main() {
    let sin = std::io::stdin();
    let scan = &mut Scanner::new(sin.lock());
    let sout = std::io::stdout();
    let out = &mut BufWriter::new(sout.lock());
    run(scan, out);
}

pub struct Scanner<R> {
    reader: R,
    buffer: Vec<String>,
}
impl<R: ::std::io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![],
        }
    }
    pub fn token<T: ::std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
    #[allow(unused)]
    pub fn token_bytes(&mut self) -> Vec<u8> {
        let s = self.token::<String>();
        return s.as_bytes().into();
    }
}

// BIT 156 ms
pub fn solve(scan: &mut Scanner<impl BufRead>, out: &mut impl Write) {
    let n = scan.token::<usize>();
    let mut a = Vec::new();
    let mut hs = Vec::new();
    for i in 0..n {
        let l = scan.token::<i64>();
        let r = scan.token::<i64>();
        hs.extend([l,r]);
        a.push((r, l, i))
    }
    a.sort_unstable();
    hs.sort_unstable();
    let mut p = BIT::new(n*2);
    let mut ans = vec![0; n];
    for &(_, l, i) in a.iter() {
        let z = hs.partition_point(|x|*x<l);
        ans[i] = p.sum_interval(z+1,n*2+1);
        p.add_point(z+1,1);
    }
    for v in ans {
        writeln!(out, "{}", v).ok();
    }
}

pub fn run(scan: &mut Scanner<impl BufRead>, out: &mut impl Write) {
    solve(scan, out)
}
// https://codeforces.com/problemset/problem/652/D
// 本模板由 https://github.com/liuliangcan/play_with_python/blob/main/tools/gen_code_tool/gen_template.py 自动生成;中文题面描述可移步

pub struct BIT {
    c: Vec<i64>,
    n: usize,
}
impl BIT {
    pub fn new(n: usize) -> Self {
        Self {
            c: vec![0; n + 2],
            n: n,
        }
    }
    /// 给下标i位置+v,注意i是1-indexed
    pub fn add_point(&mut self, mut i: usize, v: i64) {
        while i <= self.n {
            while i <= self.n {
                self.c[i] += v;
                i += self.low_bit(i);
            }
        }
    }
    /// 计算[..i]的前缀和,包含i,注意下标1-indexed
    pub fn sum_prefix(&mut self, mut i: usize) -> i64 {
        let mut s = 0;
        while i >= 1 {
            s += self.c[i];
            i &= i - 1;
        }
        return s;
    }
    /// 计算[l,r]闭区间的和,注意下标1-indexed
    #[allow(unused)]
    pub fn sum_interval(&mut self, l: usize, r: usize) -> i64 {
        return self.sum_prefix(r) - self.sum_prefix(l - 1);
    }

    pub fn low_bit(&self, x: usize) -> usize {
        let x = x as i64;
        return (x & (-x)) as usize;
    }
    /// 查找[i..]后第一个>=0的位置,包含i,注意i是1-indexed
    pub fn min_right(&mut self, i: usize) -> usize {
        let p = self.sum_prefix(i);
        if i == 1 {
            if p > 0 {
                return i;
            }
        } else {
            if p > self.sum_prefix(i - 1) {
                return i;
            }
        }
        let (mut l, mut r) = (i, self.n + 1);
        while l + 1 < r {
            let mid = (l + r) >> 1;
            if self.sum_prefix(mid) > p {
                r = mid
            } else {
                l = mid
            }
        }
        return r;
    }
}

三、其他

四、更多例题

五、参考链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值