【洛谷】【线段树】P1047 校门外的树

时间:2022-12-17 19:56:07

【题目描述:】

某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。

由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。

【输入格式:】

输入文件tree.in的第一行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。

【输出格式:】

输出文件tree.out包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

【洛谷】【线段树】P1047 校门外的树【洛谷】【线段树】P1047 校门外的树
输入样例#1500 3
150 300
100 200
470 471
输出样例#1298
输入输出样例

 

【算法分析:】

使用线段树来维护数轴上的点的状态,作为线段树例题虽然水也有些需要注意的地方

左端点从0开始,建树时叶子节点直接赋成1,

lazy-tag开成bool型表示这个区间被清零.

修改(及标记下传)时不必管要加几或减几,直接把区间清零

由于最后是输出[0, n]的树的数量,直接输出线段树的第一个节点就好,不需要支持查询

 

【代码:】

 1 //校门外的树
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 const int MAXN = 10000 + 2;
 7 
 8 int n, m;
 9 struct Segment {
10     int sum;
11     bool lazy;
12 }t[MAXN << 2];
13 
14 inline int read() {
15     int x = 0, f = 1; char ch = getchar();
16     while(ch < '0' || ch > '9') {
17         if(ch == '-') f = -1;
18         ch = getchar();
19     }
20     while(ch >= '0' && ch <= '9')
21         x = (x << 3) + (x << 1) + ch - 48, ch = getchar();
22     return x * f;
23 }
24 
25 void Build(int o, int l, int r) {
26     if(l == r) t[o].sum = 1;
27     else {
28         int mid = (l + r) >> 1;
29         Build(o << 1, l, mid);
30         Build(o << 1|1, mid + 1, r);
31         t[o].sum = t[o << 1].sum + t[o << 1|1].sum;
32     }
33 }
34 inline void down(int o, int len) {
35     if(!t[o].lazy) return;
36     t[o << 1].sum = 0;
37     t[o << 1|1].sum = 0;
38     t[o << 1].lazy = 1;
39     t[o << 1|1].lazy = 1;
40     t[o].lazy = 0;
41 }
42 void Update(int o, int l, int r, int ul, int ur) {
43     if(ul <= l && r <= ur) {
44         t[o].sum = 0;
45         t[o].lazy = 1;
46     }
47     else {
48         down(o, r - l + 1);
49         int mid = (l + r) >> 1;
50         if(ul <= mid) Update(o << 1, l, mid, ul, ur);
51         if(ur > mid) Update(o << 1|1, mid + 1, r, ul, ur);
52         t[o].sum = t[o << 1].sum + t[o << 1|1].sum;
53     }
54 }
55 
56 int main() {
57     n = read(), m = read();
58     Build(1, 0, n);
59     for(int i = 1; i <= m; ++i) {
60         int l = read(), r = read();
61         Update(1, 0, n, l, r);
62     }
63     printf("%d\n", t[1].sum);
64 }