线段树,懒标记

### **问题场景**
想象你有一棵家族树,根节点是爷爷,每个节点代表一个家庭成员,他们各自有一个钱包金额。现在需要支持两种操作:
1. **给某个家庭成员及其所有晚辈发红包**(整个子树的钱包增加)。
2. **查询某个家庭成员及其所有晚辈的钱包金额的平方和**(例如计算家族财富分布)。

我们需要高效处理这两种操作,即使家族成员数量庞大。

---

### **核心思路**
#### **1. 将树“拍扁”成数组(DFS序)**
- **问题**:树的结构复杂,直接操作子树困难。
- **解决**:通过**DFS遍历**记录每个节点的“进入时间”和“离开时间”,将子树转化为连续区间。
  - **进入时间**:第一次访问节点的时间戳(类似上班打卡)。
  - **离开时间**:完成该节点所有子节点访问的时间戳(类似下班打卡)。

**示例**:
```
树结构:
    1
   / \
  2   3
 / \
4   5

DFS遍历顺序:1 -> 2 -> 4 -> 5 -> 3
进入时间:in[1]=1, in[2]=2, in[4]=3, in[5]=4, in[3]=5
离开时间:out[1]=5, out[2]=4, out[4]=3, out[5]=4, out[3]=5
```
- 节点2的子树对应区间 `[in[2], out[2]] = [2,4]`,包含节点2、4、5。

---

#### **2. 线段树:高效管理区间**
- **线段树**是一种数据结构,可以快速处理**区间查询**和**区间更新**。
- **结构**:将数组划分成多个区间,每个树节点存储一个区间的统计值(如和、平方和)。
- **示例**:
  - 数组 `[A, B, C, D]` 的线段树:
    ```
            [A-D](总和)
           /     \
      [A-B]      [C-D]
      /   \      /   \
    [A]  [B]  [C]  [D]
    ```

---

#### **3. 懒标记(Lazy Propagation)**
- **问题**:频繁更新整个区间效率低(如给1万人发红包,逐个更新太慢)。
- **解决**:延迟更新,先记录“欠账”,需要时再实际更新。
  - **懒标记**:记录某个区间需要增加的值,暂时不传递到子节点。
  - **触发时机**:当需要查询或更新子区间时,才将懒标记下推。

**示例**:
- 给区间`[1-4]`发红包+10,先标记该区间懒标记为10,不更新子节点。
- 当查询子区间`[1-2]`时,才将懒标记下推,并更新实际值。

---### **代码逐行解析**
#### **1. 输入与初始化**
```java

// 读取输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken()); // 节点数
Q = Integer.parseInt(st.nextToken()); // 操作数

// 读取每个节点的初始金额
weight = new int[N + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= N; i++) {
    weight[i] = Integer.parseInt(st.nextToken());
}

// 构建树的邻接表
tree = new ArrayList[N + 1];
for (int i = 1; i <= N; i++) {
    tree[i] = new ArrayList<>();
}
for (int i = 1; i < N; i++) {
    st = new StringTokenizer(br.readLine());
&n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值