【线段树 + 扫描线】poj 1177 pictures 矩形周长并

来源:互联网 发布:自动配色软件 编辑:程序博客网 时间:2024/05/16 11:04

和矩形面积并的思路类似,只是累加周长时需要同时考虑竖向边和横向边,在线段树节点中需要维护一个水平线段数目的变量。数据的范围较小,不需要进行离散化。

#include <vector>#include <list>#include <limits.h>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <string.h>#include <stdlib.h>#include <cassert>using namespace std;struct Node {int left, right, lc, rc, cnt, total, hcnt;bool top, bottom;Node() { left = right = lc = rc = -1; cnt = total = hcnt = 0; top = bottom = false; }};int ptr = 0;Node tree[40005];struct Line {int x, y1, y2;bool left;Line(int _x, int _y1, int _y2, bool _left): x(_x), y1(_y1), y2(_y2), left(_left) {}};bool cmp(const Line& n1, const Line& n2) { return n1.x < n2.x; }void build_tree(int low, int up, int root) {tree[root].left = low;tree[root].right = up;if (up - low <= 1) return;int mid = (low + up) / 2;++ptr; tree[root].lc = ptr;build_tree(low, mid, ptr);++ptr; tree[root].rc = ptr;build_tree(mid, up, ptr);return;}void update_node(int root) {if (tree[root].cnt > 0) {tree[root].total = tree[root].right - tree[root].left;tree[root].top = tree[root].bottom = true;tree[root].hcnt = 2;return;}if (tree[root].right - tree[root].left <= 1) {tree[root].total = 0;tree[root].top = tree[root].bottom = false;tree[root].hcnt = 0;}else {int lchild = tree[root].lc;int rchild = tree[root].rc;tree[root].total = tree[lchild].total + tree[rchild].total;if (tree[lchild].top) tree[root].top = true; else tree[root].top = false;if (tree[rchild].bottom) tree[root].bottom = true; else tree[root].bottom = false;tree[root].hcnt = tree[lchild].hcnt + tree[rchild].hcnt;if (tree[lchild].bottom && tree[rchild].top) tree[root].hcnt -= 2;}return;}void insert_node(int low, int up, int root) {if (low <= tree[root].left && up >= tree[root].right) {++tree[root].cnt;update_node(root);return;}assert(tree[root].right - tree[root].left > 1);int mid = (tree[root].right + tree[root].left) / 2;if (up <= mid) insert_node(low, up, tree[root].lc);else if (low >= mid) insert_node(low, up, tree[root].rc);else {insert_node(low, mid, tree[root].lc);insert_node(mid, up, tree[root].rc);}update_node(root);return;}void delete_node(int low, int up, int root) {if (low <= tree[root].left && up >= tree[root].right) {assert(tree[root].cnt > 0);--tree[root].cnt;update_node(root);return;}assert(tree[root].right - tree[root].left > 1);int mid = (tree[root].right + tree[root].left) / 2;if (up <= mid) delete_node(low, up, tree[root].lc);else if (low >= mid) delete_node(low, up, tree[root].rc);else {delete_node(low, mid, tree[root].lc);delete_node(mid, up, tree[root].rc);}update_node(root);return;}vector<Line> lines;int main() {int N, maxy = INT_MIN, miny = INT_MAX;cin >> N;if (N == 0) { cout << 0 << endl; return 0; }for (int i = 0; i < N; ++i) {int x1, x2, y1, y2;cin >> x1 >> y1 >> x2 >> y2;lines.push_back(Line(x1, y1, y2, true));lines.push_back(Line(x2, y1, y2, false));maxy = max(maxy, max(y1, y2));miny = min(miny, min(y1, y2));}sort(lines.begin(), lines.end(), cmp);build_tree(miny, maxy, 0);int res = 0, prev = 0;for (int i = 0; i < lines.size(); ++i) {if (lines[i].left) insert_node(lines[i].y1, lines[i].y2, 0);else delete_node(lines[i].y1, lines[i].y2, 0);res += abs(prev - tree[0].total);prev = tree[0].total;if (i + 1 < lines.size())res += tree[0].hcnt * (lines[i + 1].x - lines[i].x);}cout << res << endl;return 0;}


0 0
原创粉丝点击