Codeforces 35E Parade 扫描线
题意:
给出\(n\)个底边在\(x\)轴上的矩形,求外面的轮廓线顶点。
分析:
将每个矩形拆成两个事件:\(\\\{ l, y, + \\\}\)和\(\\\{ r, y, - \\\}\)分别表示在扫描先到\(l\)位置将\(y\)插入数据结构,和扫描线到\(r\)位置将\(y\)从数据结构种删除。
并且该数据结构支持查询最大值
维护数据结构中的当前最大值,每当最大值发生变化时,便找到轮廓线上的两个点\((x,preH)\),\((x,curH)\)。
初始时将\(0\)加入数据结构表示地平线,就不用特判集合是否非空。
STL中的multiset就可以完成上述操作。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility>
#include <set>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
multiset<int> S;
vector<PII> event, ans;
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n; scanf("%d", &n);
for(int i = 0; i < n; i++) {
int y, l, r; scanf("%d%d%d", &y, &l, &r);
event.push_back(make_pair(l, y));
event.push_back(make_pair(r, -y));
}
sort(event.begin(), event.end());
S.insert(0);
int hmax = 0;
for(int i = 0, j; i < n * 2; i = j) {
for(j = i; j < n * 2 && event[i].first == event[j].first; j++) {
if(event[j].second > 0) S.insert(event[j].second);
else S.erase(S.lower_bound(-event[j].second));
}
if((*S.rbegin()) != hmax) {
ans.push_back(make_pair(event[i].first, hmax));
ans.push_back(make_pair(event[i].first, hmax = (*S.rbegin())));
}
}
printf("%d\n", ans.size());
for(int i = 0; i < ans.size(); i++) {
printf("%d %d\n", ans[i].first, ans[i].second);
}
return 0;
}