题面链接:POJ – 2528
题意:$N(1 \leq N \leq 10^4)$个人贴海报,每张海报的左右端点$1 \leq l_i, r_i \leq 10^7$,求出最后还能看见多少张海报。
这$N$张海报是按顺序贴的,那么越往后贴的一定在最上面。我们可以先记录下贴海报的顺序,然后从最后一张往前扫一遍。如果当前第$i$个海报的区间$[l_i, r_i]$内有没有被贴的空间,那么这个海报就可以被看到。
由此我们把这个问题转化为了一个区间覆盖问题,考虑线段树,我们可以用0和1来表示每个点的状态,维护区间最小值,如果区间最小值为0则说明这个区间有未被贴的空间,如果最小值为1(即全1)则说明这个区间没有空位了,$10^7$级别需要离散化。离散化时应注意如果存在点$x$和$y$并且$y-x>1$,那么要再加一个点$x+1$进离散化点集中,原因是例如$[1, 10], [1, 5], [8, 10]$的区间按照简单的方法离散化之后$[1,5]$和$[8,10]$会覆盖$[1,10]$,实际上中间还有$[6,7]$的可行空间。
有几个注意点:
- 离散化尽量使用sort + unique的方法,使用set + map时间常数比较大。
- 线段树数组和lazy-tag数组可以使用bool类型存,memset的时候节省时间。
- 最多是40000个点,不是20000个。
- 数据比较弱,离散化错误也能过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
#include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <map> #include <climits> using namespace std; typedef long long LL; void getInt(LL &x) { x = 0; char ch = getchar(); LL sgn = 1; while (ch < '0' || ch > '9') { if (ch == '-') sgn = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } x *= sgn; } const LL maxn = 10000 + 5; LL T, n, ql[maxn], qr[maxn]; const LL maxSize = 40000 * 4 + 5; bool tree[maxSize], tag[maxSize]; inline LL lson(LL x) { return x << 1; } inline LL rson(LL x) { return x << 1 | 1; } inline void pushUp(LL o) { tree[o] = min(tree[lson(o)], tree[rson(o)]); } inline void pushDown(LL o) { if (tag[o] == 0) return; tag[lson(o)] = tag[o]; tag[rson(o)] = tag[o]; tree[lson(o)] = tag[o]; tree[rson(o)] = tag[o]; tag[o] = 0; } void change(LL o, LL l, LL r, LL L, LL R, LL v) { if (L <= l && r <= R) { tree[o] = v; tag[o] = v; return; } LL mid = (l + r) >> 1; pushDown(o); if (L <= mid) change(lson(o), l, mid, L, R, v); if (R >= mid + 1) change(rson(o), mid + 1, r, L, R, v); pushUp(o); } LL query(LL o, LL l, LL r, LL L, LL R) { if (L <= l && r <= R) { return tree[o]; } LL mid = (l + r) >> 1, ret = INT_MAX; pushDown(o); if (L <= mid) ret = min(ret, query(lson(o), l, mid, L, R)); if (R >= mid + 1) ret = min(ret, query(rson(o), mid + 1, r, L, R)); return ret; } LL dis[maxn * 4]; int main() { getInt(T); for (LL cs = 1; cs <= T; ++cs) { getInt(n); LL disTot = 0; for (LL i = 1; i <= n; ++i) { getInt(ql[i]); dis[++disTot] = ql[i]; getInt(qr[i]); dis[++disTot] = qr[i]; } sort(dis + 1, dis + disTot + 1); LL cnt = unique(dis + 1, dis + disTot + 1) - dis; disTot = cnt; for (LL i = 2; i <= cnt; ++i) { if (dis[i] - dis[i - 1] > 1) dis[++disTot] = dis[i - 1] + 1; } sort(dis + 1, dis + disTot + 1); memset(tree, 0, sizeof tree); memset(tag, 0, sizeof tag); LL ans = 0; for (LL i = n; i >= 1; --i) { LL tl = lower_bound(dis + 1, dis + disTot + 1, ql[i]) - dis; LL tr = lower_bound(dis + 1, dis + disTot + 1, qr[i]) - dis; LL ask = query(1, 1, disTot, tl, tr); if (ask == 0) { ++ans; change(1, 1, disTot, tl, tr, 1); } } printf("%lld\n", ans); } return 0; } |
说点什么