[CF35E] Parade - 扫描线
Description
给出 n 个底边在 x 轴上的矩形,求外面的轮廓线顶点。
Solution
考虑扫描线,用一个 multiset 维护当前穿过的所有矩形
一个矩形转化为两个事件:添加一个数和删除一个数
如果操作完后集合的 max 和操作之前不同,那么它就会贡献两个顶点
#include <bits/stdc++.h>
using namespace std;
signed main()
{
ios::sync_with_stdio(false);
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
cin >> n;
vector<pair<int, int>> vec;
for (int i = 0; i < n; i++)
{
int h, x, y;
cin >> h >> x >> y;
vec.push_back({x, h});
vec.push_back({y, -h});
}
sort(vec.begin(), vec.end());
vector<pair<int, int>> ans;
multiset<int> ms;
ms.insert(0);
for (int l = 0; l < vec.size();)
{
int r = l;
int h_o = *ms.rbegin();
while (r < vec.size() && vec[l].first == vec[r].first)
{
auto [x, h] = vec[r];
if (h > 0)
ms.insert(h);
else
ms.erase(ms.find(-h));
++r;
if (r > 2 * n)
break;
}
int h_n = *ms.rbegin();
if (h_o != h_n)
{
ans.push_back({vec[l].first, h_o});
ans.push_back({vec[l].first, h_n});
}
l = r;
}
cout << ans.size() << endl;
for (auto [x, y] : ans)
cout << x << " " << y << endl;
}