11247: 【原1247】老鹿召唤树人
题目
题目描述
author: Xingdong Li 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1247
Description
玩过魔兽争霸3的同学们都知道暗夜精灵有一个英雄叫老鹿,他有一个技能是召唤树人。在这个过程中,他会把一定范围内的树变成树人。现在我们假设老鹿面前有一排树,他们的编号是0,1,2,...,L。假设技能覆盖的范围由两个整数给出,在这个范围内的树会全部变成树人。我们现在要知道在老鹿释放了M次召唤树人的技能后还剩下几棵树。
Input Format
第一行:输入两个整数L,M。L代表树木最大的编号,M代表老鹿释放召唤树人技能的次数。L和M之间用一个空格隔开。
接下来的M行:每行都有两个整数,这两个整数由一个空格隔开,表示老鹿技能的释放范围(两端的树也在范围内)。
Output Format
输出一行,这一行只有一个整数,表示在释放技能之后还剩余的树的数目。
Sample Input
500 2
150 200
180 210
Sample Output
440
Hint
对于20%的数据,技能覆盖的范围没有重合的部分;对于其他的数据,范围有重合的情况。
L的大小范围:\( 1 \leq L \leq 10000 \)
M的大小范围:\( 1 \leq M \leq 100 \)
ligongzzz's solution
#include "iostream"
#include "cstdio"
#include "cstring"
#include "cmath"
using namespace std;
class node {
public:
int left = 0, right = 0;
int val = 0;
bool flag = false;
};
node smt[100009];
void build_tree(int l, int r, int root) {
smt[root].left = l;
smt[root].right = r;
if (l == r - 1) {
smt[root].val = 1;
return;
}
int mid = (l + r) >> 1;
build_tree(l, mid, root * 2);
build_tree(mid, r, root * 2 + 1);
smt[root].val = smt[root * 2].val + smt[root * 2 + 1].val;
}
void push_down(int root) {
if (smt[root].flag) {
smt[root].flag = false;
smt[root * 2].val = 0;
smt[root * 2 + 1].val = 0;
smt[root * 2].flag = true;
smt[root * 2 + 1].flag = true;
}
}
void update(int l, int r, int root) {
if (l <= smt[root].left && smt[root].right <= r) {
smt[root].val = 0;
smt[root].flag = true;
return;
}
int mid = (smt[root].left + smt[root].right) >> 1;
push_down(root);
if (l < mid)
update(l, r, root * 2);
if (r > mid)
update(l, r, root * 2 + 1);
smt[root].val = smt[root * 2].val + smt[root * 2 + 1].val;
}
int query(int l, int r, int root) {
if (l <= smt[root].val && smt[root].val <= r) {
return smt[root].val;
}
int mid = (smt[root].left + smt[root].right) >> 1;
push_down(root);
int ans = 0;
if (l < mid) {
ans += query(l, r, root * 2);
}
if (r > mid) {
ans += query(l, r, root * 2 + 1);
}
return ans;
}
int main() {
int M, L;
scanf("%d %d", &L, &M);
build_tree(0, L + 1, 1);
for (; M > 0; --M) {
int a, b;
scanf("%d %d", &a, &b);
update(a, b + 1, 1);
}
printf("%d", query(0, L + 1, 1));
return 0;
}
yyong119's solution
#include <iostream>
#define MAX_N 10000
using namespace std;
int tree[MAX_N << 2];
int n, m;
void update(int d, int dl, int dr, int l, int r) {
if (dl == dr) tree[d] = 1;
else {
int mid = (dl + dr) >> 1;
if (r <= mid) update(d << 1, dl, mid, l, r);
else if (l > mid) update(d << 1 | 1, mid + 1, dr, l, r);
else {
update(d << 1, dl, mid, l, mid);
update(d << 1 | 1, mid + 1, dr, mid + 1, r);
}
tree[d] = tree[d << 1] + tree[d << 1 | 1];
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
while(m--) {
int l, r;
cin >> l >> r;
update(1, 1, n + 1, l + 1, r + 1);
}
cout << n + 1 - tree[1] << endl;
return 0;
}