POJ 2528 Mayor’s posters
Description
给N个海报,每个海报有L,R,表示这块区域被覆盖,问最后有多少块区域被覆盖
Algorithm
线段树
每个节点的附加信息v的意义是
- 这块区域没有任何一个海报覆盖 v = 0
- 这块区域内(不完全重合)有不止一块海报覆盖 v = 0
- 这块区域只有一块海报覆盖 v = i (i 为第 i 个海报)
线段树三个函数
-
build 建树,没什么好说
-
update
-
如果完全覆盖,就更新v
-
否则就把root的两个子节点变成v 同时把该root节点变成0
-
向下递归更新 注意是三种情况
-
-
cal 最后统计被覆盖的区域数
- 如果 v > 0 表示这块区域被海报 v 完全覆盖 ans++, 注意用used记录
- v = 0 则向下递归
离散化
本题l,r很长,所以需要离散化,实际上离散化的代码并不长,具体可看代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 10000 + 9;
pair<int, int> a[MAXN], b[MAXN];
vector<int> v;
bool used[MAXN];
int getId(int x)
{
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
struct Node
{
int l, r, v;
};
Node tree[10 * MAXN];
void build(int root, int l, int r)
{
tree[root].l = l;
tree[root].r = r;
tree[root].v = 0;
if (l == r) return;
int mid = (l + r) / 2;
build(2 * root, l, mid);
build(2 * root + 1, mid + 1, r);
}
void update(int root, int l, int r, int v)
{
// << root << ' ' << l << ' ' << r << ' ' << v << ' ' << tree[root].l << ' ' << tree[root].r << endl;
if (tree[root].l == l && tree[root].r == r) {
tree[root].v = v;
return;
}
if (tree[root].v != 0) {
tree[2 * root].v = tree[root].v;
tree[2 * root + 1].v = tree[root].v;
tree[root].v = 0;
}
int mid = (tree[root].l + tree[root].r) / 2;
if (r <= mid) {
update(root * 2, l, r, v);
return;
}
if (l > mid) {
update(root * 2 + 1, l, r, v);
return;
}
update(root * 2, l, mid, v);
update(root * 2 + 1, mid + 1, r, v);
}
int ans = 0;
void cal(int root)
{
if (tree[root].v > 0) {
if (!used[tree[root].v]) {
ans++;
used[tree[root].v] = true;
}
return;
}
cal(2 * root);
cal(2 * root + 1);
}
void solve()
{
v.clear();
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int l, r;
scanf("%d%d", &l, &r);
v.push_back(l);
v.push_back(r);
a[i].first = l;
a[i].second = r;
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for (int i = 0; i < n; i++) {
b[i].first = getId(a[i].first);
b[i].second = getId(a[i].second);
}
build(1, 1, v.size());
for (int i = 0; i < n; i++) {
update(1, b[i].first, b[i].second, i + 1);
}
memset(used, 0, sizeof(used));
ans = 0;
cal(1);
cout << ans << endl;
}
int main()
{
//freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) {
solve();
}
}