HDOJ 1698 - Just a Hook

Advanced Data Structures :: Segment Tree


Description

Dota中的屠夫有个技能可以伸出一个钩子。

当然,这个和题目一点关系都没有。

一个钩子,可以被看成是好几节的金属节链接起来的。

最初钩子每节都是铜造的,一节铜是价值1。

之后,我们去改变某一段钩子的材料,变成银(价值2)或者金(价值3),或者变回铜。

输入钩子的长度,和如何去改变。

输出最后钩子的总价值。


Type

Advanced Data Structures :: Segment Tree


Analysis

经典的线段树,成段更新,需要用延迟标记。


如果对于每次更新,我们都化为每点去更新的话,时间复杂度会变成O(n)。

效率会降低,失去了使用线段树的意义(把n变成log n)。


但是我们可以利用延迟标记。

就是说,我们每次都更新到我们需要的值,便不再继续更新下去。

然后把需要更新下去的值记录下来。

下次如果要访问更深层次的节点,才会继续更新下去。


这样,就可以仅仅在需要的时候更新,让更新随着修改值,或者询问值的过程进行。

时间复杂度就依然为O(log n)。


Solution

// HDOJ 1698
// Just a Hook
// by A Code Rabbit

#include <cstdio>

#define LSon(x) ((x) << 1)
#define RSon(x) ((x) << 1 | 1)

const int MAXN = 100002;
const int ROOT = 1;

struct Seg {
    int w;
    int flag;
};

struct SegTree {
    Seg node[MAXN << 2];
    void Update(int pos) { node[pos].w = node[LSon(pos)].w + node[RSon(pos)].w; }
    void Build(int l, int r, int pos) {
        node[pos].flag = 0;
        if (l == r) { node[pos].w = 1; return; }
        int m = l + r >> 1;
        Build(l, m, LSon(pos));
        Build(m + 1, r, RSon(pos));
        Update(pos);
    }
    void Push(int l, int r, int pos) {
        Seg& father = node[pos];
        Seg& lson = node[LSon(pos)];
        Seg& rson = node[RSon(pos)];
        if (father.flag) {
            int m = l + r >> 1;
            lson.w = father.flag * (m + 1 - l);
            rson.w = father.flag * (r - m);
            lson.flag = rson.flag = father.flag;
            father.flag = 0;
        }
    }
    void Modify(int l, int r, int pos, int x, int y, int z) {
        if (x <= l && r <= y) {
            node[pos].w = z * (r + 1 - l);
            node[pos].flag = z;
            return;
        }
        Push(l, r, pos);
        int m = l + r >> 1;
        if (x <= m) Modify(l, m, LSon(pos), x, y, z);
        if (y > m) Modify(m + 1, r, RSon(pos), x, y, z);
        Update(pos);
    }
    int Query(int l, int r, int pos, int x, int y) {
        if (x <= l && r <= y) return node[pos].w;
        Push(l, r, pos);
        int m = l + r >> 1;
        int res = 0;
        if (x <= m) res += Query(l, m, LSon(pos), x, y);
        if (y > m) res += Query(m + 1, r, RSon(pos), x, y);
        return res;
    }
};

int n, q;
int x, y, z;

SegTree tree;

int main() {
    int tot_case;
    scanf("%d", &tot_case);
    for (int t = 0; t < tot_case; t++) {
        scanf("%d", &n);
        scanf("%d", &q);
        tree.Build(1, n, ROOT);
        for (int i = 0; i < q; ++i) {
            scanf("%d%d%d", &x, &y, &z);
            tree.Modify(1, n, ROOT, x, y, z);
        }
        printf("Case %d: The total value of the hook is %d.\n", t + 1, tree.Query(1, n, ROOT, 1, n));
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值