18130 繁忙的公路

### 详细分析

为了高效处理车辆信息的更新和查询,我们可以使用线段树(Segment Tree)。线段树是一种平衡二叉树,可以在对数时间内完成区间更新和查询操作,非常适合处理这种区间查询问题。

### 思路

1. **初始化**:创建一个大小为 `N` 的数组 `cars`,初始值为 0,表示每��标记处的车辆数。
2. **线段树构建**:构建一个线段树来维护车辆数的区间和。
3. **处理输入**:根据输入的探头信息和查询请求,更新线段树或查询区间和。
4. **输出结果**:对于每个查询请求,输出对应区间的车辆总数。

### 伪代码

1. 读取输入的 `N` 和 `M`。
2. 初始化一个大小为 `N` 的数组 `cars`,初始值为 0。
3. 构建线段树。
4. 遍历 `M` 条探头信息或查询请求:
   - 如果是探头信息 `H x y`,更新线段树,将标记 `x` 处的车辆数增加 `y`。
   - 如果是查询请求 `Q l r`,查询线段树,输出区间 `[l, r]` 的车辆总数。

### C++代码

#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;

class SegmentTree {
private:
    vector<long long> tree;
    int n;

    void build(vector<long long>& arr, int node, int start, int end) {
        if (start == end) {
            tree[node] = arr[start];
        } else {
            int mid = (start + end) / 2;
            int left_node = 2 * node + 1;
            int right_node = 2 * node + 2;
            build(arr, left_node, start, mid);
            build(arr, right_node, mid + 1, end);
            tree[node] = tree[left_node] + tree[right_node];
        }
    }

    void update(int node, int start, int end, int idx, long long val) {
        if (start == end) {
            tree[node] += val;
        } else {
            int mid = (start + end) / 2;
            int left_node = 2 * node + 1;
            int right_node = 2 * node + 2;
            if (start <= idx && idx <= mid) {
                update(left_node, start, mid, idx, val);
            } else {
                update(right_node, mid + 1, end, idx, val);
            }
            tree[node] = tree[left_node] + tree[right_node];
        }
    }

    long long query(int node, int start, int end, int l, int r) {
        if (r < start || end < l) {
            return 0;
        }
        if (l <= start && end <= r) {
            return tree[node];
        }
        int mid = (start + end) / 2;
        int left_node = 2 * node + 1;
        int right_node = 2 * node + 2;
        long long sum_left = query(left_node, start, mid, l, r);
        long long sum_right = query(right_node, mid + 1, end, l, r);
        return sum_left + sum_right;
    }

public:
    SegmentTree(int size) {
        n = size;
        tree.resize(4 * n, 0);
    }

    void build(vector<long long>& arr) {
        build(arr, 0, 0, n - 1);
    }

    void update(int idx, long long val) {
        update(0, 0, n - 1, idx, val);
    }

    long long query(int l, int r) {
        return query(0, 0, n - 1, l, r);
    }
};

int main() {
    int N, M;
    scanf("%d %d", &N, &M);

    vector<long long> cars(N, 0);
    SegmentTree segTree(N);
    segTree.build(cars);

    for (int i = 0; i < M; ++i) {
        char type;
        int x, y;
        scanf(" %c", &type);
        if (type == 'H') {
            scanf("%d %d", &x, &y);
            segTree.update(x - 1, y);
        } else if (type == 'Q') {
            scanf("%d %d", &x, &y);
            printf("%lld\n", segTree.query(x - 1, y - 1));
        }
    }

    return 0;
}

### 结论

通过使用线段树,我们可以高效地处理车辆信息的更新和查询操作。线段树的构建、更新和查询操作的时间复杂度均为 `O(log N)`,能够满足题目中 `N` 和 `M` 的规模要求。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值