HDU 1698 Just a Hook [线段树+区间修改为一个值+区间查询]

\(HDU\) \(1698\) \(Just\) \(a\) \(Hook\)

一、经验总结

  • \(HDU\) 是杭州电子科技大学的简称,\(POJ\)是北京大学\(OJ\)简称
  • 因读入量较大,使用cin读入直接TLE,换用scanfAC,看来能用scanf最好以后用scanf!
  • \(HDU\)\(POJ\)不支持万能头文件,需要小心替换库文件

二、题目理解

给你一个长 \(n\) 的序列,初始值全为 \(1\)\(q\) 次操作,每次将 \([ x, y ]\) 的值改为 \(z\) ,问最后整个序列的和为多少?

三、实现代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 100010;

int n, q;
struct Node {
    int l, r;
    LL sum;
    int tag;
} tr[N << 2];

void pushup(int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void bulid(int u, int l, int r) {
    tr[u] = {l, r};
    if (l == r) {
        tr[u].sum = 1;
        return;
    }
    int mid = (l + r) >> 1;
    bulid(u << 1, l, mid), bulid(u << 1 | 1, mid + 1, r);
    pushup(u);
}

void pushdown(int u) {
    Node &root = tr[u], &ls = tr[u << 1], &rs = tr[u << 1 | 1];
    if (root.tag) { // 如果懒标记不为零,需要向儿子们传递懒标记
        ls.tag = root.tag, ls.sum = (LL)(ls.r - ls.l + 1) * root.tag;
        rs.tag = root.tag, rs.sum = (LL)(rs.r - rs.l + 1) * root.tag;
        root.tag = 0; // 清空懒标记
    }
}

void modify(int u, int l, int r, int v) {
    if (l <= tr[u].l && tr[u].r <= r) {
        tr[u].sum = (LL)v * (tr[u].r - tr[u].l + 1);
        tr[u].tag = v;
        return;
    }

    pushdown(u); // 没有完全覆盖则分裂
    int mid = (tr[u].l + tr[u].r) >> 1;
    if (l <= mid) modify(u << 1, l, r, v);
    if (r > mid) modify(u << 1 | 1, l, r, v);
    pushup(u);
}

LL query(int u, int l, int r) {
    if (l > tr[u].r || r < tr[u].l) return 0;           // 递归出口,不在我管辖范围内的情况,返回0
    if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum; // 完整区间覆盖,返回区间和
    // 没有完全命中,开始分裂
    pushdown(u);
    // 左边+右边
    return query(u << 1, l, r) + query(u << 1 | 1, l, r);
}

int main() {
    // 加快读入
    ios::sync_with_stdio(false), cin.tie(0);

    int T;
    cin >> T;
    int cas = 1;
    while (T--) {
        cin >> n;                 // 线段的区间[1~n]
        memset(tr, 0, sizeof tr); // 因树状数组多次使用,每次需要清空
        bulid(1, 1, n);           // 构建树状数组

        cin >> q;
        while (q--) {
            int l, r, d;
            cin >> l >> r >> d;
            modify(1, l, r, d);
        }
        printf("Case %d: The total value of the hook is %lld.\n", cas++, query(1, 1, n));
    }
    return 0;
}
posted @ 2022-04-24 09:46  糖豆爸爸  阅读(43)  评论(0编辑  收藏  举报
Live2D