知识点:线段树,离散化
这个用线段树来实现,就是区间修改区间查询,区间修改就是把区间所有的数都改成一个,然后查询就是最后查询一次所有叶子结点的数字,最后统计一下不同的数字的个数就是能看到的海报的数目,但是这个题的数据有点大,所以要用离散化,这里离散化也有一个小技巧,排好序去重那一步里,两个挨着的数中间没有数的话,那么加上一个,这个可以防止出错,这里的原理还要好好想一想
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 5;
struct tree {
int l, r;
int sum, val;
};
int a[N], b[N], c[N], d[N], h[N], ans;
tree t[N * 4];
void pushdown(int p) {
if (t[p].val == -1) return;
t[p * 2].sum = (t[p * 2].r - t[p * 2].l + 1) * t[p].val;
t[p * 2 + 1].sum = (t[p * 2 + 1].r - t[p * 2 + 1].l + 1) * t[p].val;
t[p * 2].val = t[p * 2 + 1].val = t[p].val;
t[p].val = -1;
}
void build(int p, int l, int r) {
t[p].l = l; t[p].r = r;
if (l == r) {
t[p].sum = 0; t[p].val = -1;
return;
}
int mid = (l + r) / 2;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
t[p].val = -1;
}
void update(int p, int l, int r, int x) {
if (l <= t[p].l && r >= t[p].r) {
t[p].sum = (t[p].r - t[p].l + 1) * x;
t[p].val = x;
return;
}
pushdown(p);
int mid = (t[p].l + t[p].r) / 2;
if (l <= mid) update(p * 2, l, r, x);
if (r > mid) update(p * 2 + 1, l, r, x);
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
}
void query(int p) {
if (t[p].l == t[p].r) {
if (!h[t[p].sum] && t[p].sum) {
h[t[p].sum] = 1;
ans++;
}
return;
}
pushdown(p);
query(p * 2);
query(p * 2 + 1);
}
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i], &b[i]);
c[i] = a[i]; c[i + n] = b[i];
}
sort(c + 1, c + n * 2 + 1);
int cnt = 0;
for (int i = 1; i <= n * 2; i++) {
if (!cnt) d[++cnt] = c[i];
if (cnt && c[i] > c[i - 1]) {
if (c[i] - c[i - 1] > 1) d[++cnt] = c[i] - 1;
d[++cnt] = c[i];
}
}
build(1, 1, cnt);
for (int i = 1; i <= n; i++) {
int x = lower_bound(d + 1, d + cnt + 1, a[i]) - d;
int y = lower_bound(d + 1, d + cnt + 1, b[i]) - d;
update(1, x, y, i);
}
memset(h, 0, sizeof(h));
ans = 0;
query(1);
cout << ans << '\n';
}
return 0;
}