Mayor's posters
线段树+离散化
将海报覆盖的区间在线段树中进行标记,最后统计存在于树中的海报类型
由于本题的数据范围比较大,需要对坐标进行离散化。之后再递归的遍历每一个节点,将存在的标记存放到set中,最终set中元素的数量就是海报的类型
注意:
- 离散化后,区间之间的相对宽度会发生变化,比如[1, 10000]离散化后,变成[1,2],显然后者的覆盖范围要远小于前者。这点要注意,所以格外添加\(l+1\)和\(r+1\)
- 除了建树的过程外,对于访问子节点的操作都需要下放懒标记,所以在修改和询问时要
push_down
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 2e5 + 100;
struct Node {
int l, r;
int t;
} tr[N * 4];
int n, g[N], cnt;
vector<PII> v(N);
set<int> se;
inline int get(int x) {
return lower_bound(g + 1, g + cnt + 1, x) - g;
}
void build(int u, int l, int r) {
tr[u] = {l, r};
if (l == r) return;
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}
inline void push_down(int u) {
int &t = tr[u].t;
if (t) tr[u << 1].t = tr[u << 1 | 1].t = t;
t = 0;
}
void modify(int u, int l, int r, int t) {
if (tr[u].l >= l && tr[u].r <= r) tr[u].t = t;
else {
push_down(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(u << 1, l, r, t);
if (r > mid) modify(u << 1 | 1, l, r, t);
}
}
void count(int u, int l, int r) {
// printf("%d %d %d %d\n", u, tr[u].t, l, r);
if (tr[u].t) se.insert(tr[u].t);
if (l == r) return;
push_down(u);
int mid = l + r >> 1;
count(u << 1, l, mid), count(u << 1 | 1, mid + 1, r);
}
int main() {
int _T;
scanf("%d", &_T);
while (_T --) {
scanf("%d", &n);
v.clear();
se.clear();
cnt = 0;
for (int i = 0; i < n; i++) {
int l, r; scanf("%d%d", &l, &r);
v.push_back({l, r});
g[++cnt] = l, g[++cnt] = r, g[++cnt] = r + 1, g[++cnt] = l + 1;
}
sort(g + 1, g + cnt + 1);
cnt = unique(g + 1, g + cnt + 1) - g;
build(1, 1, cnt);
for (int i = 0; i < v.size(); i++) {
auto [l, r] = v[i];
l = get(l), r = get(r);
modify(1, l, r, i + 1);
}
count(1, 1, cnt);
printf("%zd\n", se.size());
}
return 0;
}
set非离散化
从后往前,将当前海报覆盖的范围的点全部删除,枚举的区间存在部分端点在set中,代表该海报没有被完全覆盖
注意:假如要删除的区间是最右边的,那么当区间内的元素会始终小于区间右边端点,此时while
循环不会停止,所以要格外假如r+1
这个点。
#include <iostream>
#include <algorithm>
#include <set>
#include <cstdio>
#include <utility>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 1000;
set<int> se;
PII q[N];
int n;
int main() {
int _T;
scanf("%d", &_T);
while (_T --) {
int res = 0;
se.clear();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int & l = q[i].first, &r = q[i].second;
scanf("%d%d", &l, &r);
se.insert(l), se.insert(r), se.insert(r + 1);
}
for (int i = n; i; i--) {
int l = q[i].first, r = q[i].second;
auto t = se.lower_bound(l);
if (*t <= r) res++;
while (*t <= r) {
se.erase(t);
t = se.lower_bound(l);
}
}
printf("%d\n", res);
}
return 0;
}