Loading

CodeForces-915E Physical Education Lessons 线段树动态开点

CodeForces-915E Physical Education Lessons 线段树动态开点

题意

实现一个数据结构支持

  • 操作1: \([l,r]\) 赋值为\(0\)
  • 操作2: \([l,r]\) 赋值为\(1\)
  • 在上述操作结束后询问\(1-n\) 的区间和

\(1-n\) 初始值均为\(1\)

\[1\leq n \leq 10^9 ,1\leq q \leq 3\cdot 10^5 \]

分析

显然此题就是简单的区间修改,可以用线段树完成,但是\(n\) 比较大,空间必然爆掉,但是\(q\) 又比较小,所以可以离散化

但是此题也可以利用线段树动态开点,简而言之就是需要的时候才开点,可以省略很多不必要的点。

空间复杂度大约为\(O(qlogn)\)

写法上也有一些区别

代码

const int M = 3e5 + 5;

int ls[M * 45], rs[M * 45], sum[M * 45], lazy[M * 45];
int id;

void push_down(int l, int r, int &rt) {
    if (lazy[rt] == -1) return;
    int mid = l + r >> 1;
    if (l != r) {
        if (!ls[rt]) ls[rt] = ++id;
        if (!rs[rt]) rs[rt] = ++id;
        lazy[rs[rt]] = lazy[rt];
        lazy[ls[rt]] = lazy[rt];
        sum[ls[rt]] = (mid + 1 - l) * lazy[rt];
        sum[rs[rt]] = (r - mid) * lazy[rt];
    } 
    lazy[rt] = -1;
}

void update(int &rt,int l,int r,int L,int R,int v) {
    if (!rt) rt = ++id;
    if (r < L || l > R) return;
    if (L <= l && R >= r) {
        lazy[rt] = v;
        sum[rt] = (r - l + 1) * v;
        return;
    }
    push_down(l, r, rt);
    int mid = l + r >> 1;
    update(ls[rt], l, mid, L, R, v);
    update(rs[rt],  mid + 1, r, L, R, v);
    sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}

int main() {
    int n, m;
    int l, r, x, y, z, rt;
    while (~scanf("%d", &n)) {
        m = readint();
        id = rt = 0;
        memset(ls, 0, sizeof ls);
        memset(rs, 0, sizeof rs);
        memset(sum, 0, sizeof sum);
        memset(lazy, -1, sizeof lazy);
        while (m--) {
            x = readint(), y = readint(), z = readint();
            if (z == 1) update(rt, 1, n, x, y, 1);
            else update(rt, 1, n, x, y, 0);
            Put(n - sum[1]);
            puts("");
        }
    }
}
posted @ 2020-08-30 19:50  MQFLLY  阅读(122)  评论(0编辑  收藏  举报