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;
}
posted @ 2016-07-27 10:06  AOQNRMGYXLMV  阅读(...)  评论(... 编辑 收藏