@(K ACMer)
题意:
一堵墙,海报覆盖于其上,问可以看到的海报有多少个?
分析:
非常典型的线段树的应用,但是此题空间过大,需要离散化,而且不是一般的离散化,因为每个坐标点代表的是一个格子,而不再是一个刻度.
普通离散化的思路是,把数据中出现的数通通由小到大的排序后去重,它对应的数组下标就是其离散化后的值,每次要用二分去数组中差这个值对应的离散化后的坐标值.
比如有这样两张海报
[1,2]
,
[4,6]
,它们显然是不相邻的,但是离散化之后就变为
[1,2]
,
[3,4]
显然相邻…也就是本来
[1,4]
在离散化之前是
[1,6]
是没有被完全覆盖的,但本题中普通离散化后就覆盖了.所以需要一个优化技巧,那就是在不连续的数中间插入一个数,让它们的不连续身份识别出来.这样只需要多增加一些离散化元素而已.
线段树的话写成区间更新即可.
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 40;
int table[maxn * 3], col[maxn * 4], l[maxn], r[maxn], n, m, t, ans;
bool hashs[maxn * 2];
void pushdown(int rt) {
if (col[rt] != -1) {
col[rt << 1] = col [rt << 1 | 1] = col[rt];
col[rt] = -1;
}
}
void update(int L, int R, int x, int l, int r, int rt) {
if (l >= L && r <= R) {
col[rt] = x;
return;
}
pushdown(rt);
int m = (l + r) >> 1;
if (L <= m) update(L, R, x, lson);
if (R >= m + 1) update(L, R, x, rson);
}
void query(int l, int r, int rt) {
if (col[rt] != -1) {
if (!hashs[col[rt]]) ans++;
hashs[col[rt]] = true;
return;
}
if (l == r) return;
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int getid(int x) {
return lower_bound(table, table + m, x) - table;
}
int main(void) {
int T;
scanf("%d", &T);
while (T--) {
memset(hashs, 0, sizeof(hashs));
ans = m = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &l[i], &r[i]);
table[m++] = l[i];
table[m++] = r[i];
}
t = 1;
sort(table, table + m);
for (int i = 1; i < m; i++) {
if (table[i] != table[i - 1]) table[t++] = table[i];
}
m = t;
for (int i = 1; i < t; i++) {
if (table[i] != table[i - 1] + 1) table[m++] = table[i - 1] + 1;
}
sort(table, table + m);
memset(col, -1, sizeof(col));
for (int i = 0; i < n; i++) {
int ll = getid(l[i]), rr = getid(r[i]);
update(ll, rr, i, 0, m, 1);
}
query(0, m, 1);
printf("%d\n", ans);
}
return 0;
}