Just a Hook

title: 题目
給定 N, Q,代表序列有 N 個元素,他們的初始值皆是 1。 接下來 Q 行,每行有三個數字 X, Y, Z,代表將序列中 X 到 Y 的元素值改成 Z。 最後輸出序列元素的和。
 
多組測資,第一個數字 T 代表有幾組測資。 對於每一組測資,第一行會輸入一個數字 N (1<=N<=100,000),下一行會輸入一個數字 Q (0<=Q<=100,000)。  
接下來 Q 行,每行有三個數字 X, Y, Z (1<=X<=Y<=N, 1<=Z<=3)
 
對於每一筆測資,輸出一個數字代表序列每個元素的總和,格式請參考範例輸出
title: input
1
10
2
1 5 2
5 9 3
 
title: output
Case 1: The total value of the hook is 24.
 
title: 思路
 
直接用线段树模拟更新该节点即其所有子节点会超时。
使用lazy技巧, 若更新到 `[0,5]` 节点时, 就在该节点打上一个`lazy = Z`的标记, 同时停止向下继续更新, 直接返回。
等到某一次又更新到 `[0,5]` 节点时, 且不是最终要找的节点, 说明需要用到该节点之后的节点, 那么就需要将上次存的lacy更新到直系子节点, 同样也不必一次更新全部子节点, 只更新自己的直系两个就行, 这两个用到那个后面会再次进行这个过程。
 
就这样可以优化很多时间复杂度。
title:代码
~~~ c ++
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l, mid, u << 1
#define rson mid + 1, r, u << 1 | 1
#define MID l + r >> 1
const int N = 1e5 + 10;
int readInt()
{
    int t;
    scanf("%d", &t);
    return t;
}
 
struct node
{
    int l, r;
    int val, lazy;
} t[N << 2];
 
void pushup(int u) { t[u].val = t[u << 1].val + t[u << 1 | 1].val; }
 
void build(int l, int r, int u = 1)
{
    t[u] = {l, r, 1, 0};
    if (l == r)
        return;
    int mid = MID;
    build(lson), build(rson);
    pushup(u);
}
 
void pushdown(node &op, int lazy)
{
    op.val = lazy * (op.r - op.l + 1);
    op.lazy = lazy;
}
 
void pushdown(int u)
{
    if (!t[u].lazy)
        return;
    pushdown(t[u << 1], t[u].lazy);
    pushdown(t[u << 1 | 1], t[u].lazy);
    t[u].lazy = 0;
}
 
void modify(int l, int r, int c, int u = 1)
{
    if (l <= t[u].l && r >= t[u].r) // 当节点在所需区间内
    {
        pushdown(t[u], c); // 更新该节点的总和, 且置lazy为更新值
        return;
    }
    pushdown(u); // 此时所需区间在该节点里面, 即需要用到该节点的子节点, 则去清除该节点的lazy, 让子节点的值加上lazy
    // 注意也不是把下面所有子节点全给更新, 只更新直系子节点, 后面用到会重复这个操作
    int mid = t[u].l + t[u].r >> 1;
    if (l <= mid)
        modify(l, r, c, u << 1);
    if (r > mid)
        modify(l, r, c, u << 1 | 1);
    pushup(u);
}
 
int main()
{
    int T = readInt();
    for (int kase = 1; kase <= T; kase++)
    {
        int n = readInt(), m = readInt();
        build(1, n);
        while (m--) // l, r, c
        {
            int l, r, c;
            scanf("%d %d %d", &l, &r, &c);
            modify(l, r, c);
        }
        printf("Case %d: The total value of the hook is %d.\n", kase, t[1].val);
    }
    return 0;
}
~~~