• codedecision P1112 区间连续段 题解 线段树


    题目描述:https://www.cnblogs.com/problems/p/P1112.html
    题目链接:http://codedecision.com/problem/1112
    线段树区间操作,每一个线段对应的点包含三个信息:

    • (l):表示这个区间最左边的点的数值;
    • (r):表示这个区间最右边的点的数值;
    • (cnt):表示这个区间有多少个数值段。

    合并的时候:

    • 根节点的 (l) 值等于左儿子节点的 (l) 值;
    • 根节点的 (r) 值等于右儿子节点的 (r) 值;
    • 根节点的 (cnt) 值取决于左儿子的 (r) 值和右儿子的 (l) 值是否相等,
      1. 如果相等,则为:左儿子的 (cnt) + 右儿子的 (cnt) - 1
      2. 否则,为:左儿子的 (cnt) + 右儿子的 (cnt)

    更新的时候,如果节点表示的这一段区间全在区间范围内,
    则将节点的 (l)(r) 都置为将要更新的值,并将节点的 (cnt) 置为 1。

    因为涉及区间操作,需要用到延迟操作。
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100100;
    struct Node {
        int l, r, cnt;
        Node () {}
        Node (int _l, int _r, int _cnt) { l = _l; r = _r; cnt = _cnt; }
    } tree[maxn<<2];
    int n, lazy[maxn<<2];
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    void push_up(int rt) {
        tree[rt].l = tree[rt<<1].l;
        tree[rt].r = tree[rt<<1|1].r;
        tree[rt].cnt = tree[rt<<1].cnt + tree[rt<<1|1].cnt - (tree[rt<<1].r == tree[rt<<1|1].l ? 1 : 0);
    }
    void push_down(int rt) {
        if (lazy[rt]) {
            lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
            tree[rt<<1].cnt = tree[rt<<1|1].cnt = 1;
            tree[rt<<1].l = tree[rt<<1].r = tree[rt<<1|1].l = tree[rt<<1|1].r = lazy[rt];
            lazy[rt] = 0;
        }
    }
    void build(int l, int r, int rt) {
        if (l == r) {
            tree[rt] = Node(0, 0, 1);
            return;
        }
        int mid = (l + r) / 2;
        build(lson);
        build(rson);
        push_up(rt);
    }
    void update(int L, int R, int v, int l, int r, int rt) {
        if (L <= l && r <= R) {
            tree[rt] = Node(v, v, 1);
            lazy[rt] = v;
            return;
        }
        push_down(rt);
        int mid = (l + r) / 2;
        if (L <= mid) update(L, R, v, lson);
        if (R > mid) update(L, R, v, rson);
        push_up(rt);
    }
    Node query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return tree[rt];
        push_down(rt);
        int mid = (l + r) / 2;
        if (L > mid) return query(L, R, rson);
        else if (R <= mid) return query(L, R, lson);
        else {
            Node a = query(L, R, lson);
            Node b = query(L, R, rson);
            return Node(a.l, b.r, a.cnt + b.cnt - (a.r == b.l ? 1 : 0));
        }
    }
    int m, x, y, a;
    string op;
    int main() {
        cin >> n >> m;
        build(1, n, 1);
        while (m --) {
            cin >> op;
            if (op == "update") {
                cin >> x >> y >> a;
                update(x, y, a, 1, n, 1);
            }
            else {
                cin >> x >> y;
                cout << query(x, y, 1, n, 1).cnt << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Intent flag 与启动模式的对应关系
    Activity的启动模式---总结
    NDK---使用,开发步骤
    自定义ViewGroup
    android:process结合activity启动模式的一次实践
    Java单元测试之覆盖率统计eclemma
    Java单元测试之JUnit篇
    结对编程1
    个人作业1——四则运算题目生成程序(基于控制台)
    Coding使用方法
  • 原文地址:https://www.cnblogs.com/codedecision/p/11785168.html
Copyright © 2020-2023  润新知