|
|
#include <bits/stdc++.h>
|
|
|
using namespace std;
|
|
|
const int N = 1e3 + 10;
|
|
|
int n, m;
|
|
|
int x[N], y[N];
|
|
|
bool flag; // 当前枚举到的海报是不是能被看到
|
|
|
|
|
|
// 推荐版本:静态离散化+区间覆盖
|
|
|
#define ls (u << 1)
|
|
|
#define rs (u << 1 | 1)
|
|
|
#define mid ((l + r) >> 1)
|
|
|
struct Node {
|
|
|
int l, r;
|
|
|
bool color; // 是不是所辖区间被完整覆盖
|
|
|
} tr[N << 2];
|
|
|
|
|
|
void pushup(int u) {
|
|
|
tr[u].color = tr[ls].color && tr[rs].color; // 只有左儿子被完整覆盖,并且,右儿子被完整覆盖,自己才是被完整覆盖
|
|
|
}
|
|
|
|
|
|
void build(int u, int l, int r) {
|
|
|
tr[u].l = l, tr[u].r = r;
|
|
|
if (l == r) return;
|
|
|
build(ls, l, mid);
|
|
|
build(rs, mid + 1, r);
|
|
|
}
|
|
|
|
|
|
void modify(int u, int L, int R) {
|
|
|
int l = tr[u].l, r = tr[u].r;
|
|
|
if (l > R || r < L) return;
|
|
|
if (tr[u].color) return; // 如果本区间原来就已经被覆盖过了,那么返回,也就不会在这段区间使得flag=true,也就是这个区域是看不到的
|
|
|
if (l >= L && r <= R) { // 如果以前没有被覆盖过,并且,本次本区域被完整覆盖,也就是第一次覆盖
|
|
|
flag = true; // 当前枚举到的海报可以被看到
|
|
|
tr[u].color = true; // 记录本区域被完整覆盖
|
|
|
return;
|
|
|
}
|
|
|
modify(ls, L, R), modify(rs, L, R);
|
|
|
pushup(u);
|
|
|
}
|
|
|
int b[N << 1], bl; // 离散化数组
|
|
|
|
|
|
int main() {
|
|
|
#ifndef ONLINE_JUDGE
|
|
|
freopen("P3740.in", "r", stdin);
|
|
|
#endif
|
|
|
// 加快读入
|
|
|
ios::sync_with_stdio(false), cin.tie(0);
|
|
|
cin >> n >> m;
|
|
|
for (int i = 1; i <= m; i++) {
|
|
|
cin >> x[i] >> y[i];
|
|
|
b[++bl] = x[i];
|
|
|
b[++bl] = y[i];
|
|
|
b[++bl] = y[i] + 1; // 区间覆盖问题的解决之道
|
|
|
}
|
|
|
// 排序+去重 (要注意b数组的范围,bl代表了它的上界!)
|
|
|
sort(b + 1, b + 1 + bl);
|
|
|
int tot = unique(b + 1, b + 1 + bl) - b - 1;
|
|
|
|
|
|
// 构建线段树
|
|
|
build(1, 1, tot);
|
|
|
|
|
|
int res = 0;
|
|
|
for (int i = m; i; i--) { // 倒序
|
|
|
flag = false; // 当前枚举到的海报是不是能被看到,默认是不能被看到
|
|
|
int L = lower_bound(b + 1, b + 1 + tot, x[i]) - b;
|
|
|
int R = lower_bound(b + 1, b + 1 + tot, y[i]) - b;
|
|
|
modify(1, L, R); // 覆盖掉【L,R】
|
|
|
if (flag) res++; // 如果当前枚举到的海报可以被看到,那么多了一张
|
|
|
}
|
|
|
// 输出答案
|
|
|
printf("%d\n", res);
|
|
|
return 0;
|
|
|
}
|