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("");
}
}
}