二次联通门 : luogu P1382 楼房
/* luogu P1382 楼房 线段树 + 扫描线 + 离散化 正解貌似是堆。。。 MMP。。。二段式线段树各种错误。。。 离散化一下横坐标 扫描线扫一下就好。。 注意判断一个横坐标上对应两个y值的情况。。。 */ #include <algorithm> #include <cstdio> #define Max 1000002 void read (int &now) { now = 0; bool temp = false; register char word = getchar (); while (word < ‘0‘ || word > ‘9‘) { if (word == ‘-‘) temp = true; word = getchar (); } while (word >= ‘0‘ && word <= ‘9‘) { now = now * 10 + word - ‘0‘; word = getchar (); } if (temp) now = -now; } inline int min (int _Curs_, int ROcs_) { return _Curs_ < ROcs_ ? _Curs_ : ROcs_; } inline int max (int _Curs_, int ROcs_) { return _Curs_ > ROcs_ ? _Curs_ : ROcs_; } struct Segment_Tree_Data { Segment_Tree_Data *Left, *Right; int l, r; int key; int Flandre; int Mid; Segment_Tree_Data () { Left = NULL; Right = NULL; key = 0; Flandre = 0; } }; struct Data_Type { int l, r; int h; bool operator < (const Data_Type &now) const { return now.l < l; } }; struct Point_Data { int x, y; }; Segment_Tree_Data *Root; class Segment_Tree_Type { public : void Build (Segment_Tree_Data *&now, int l, int r) { now = new Segment_Tree_Data (); now->l = l; now->r = r; if (l == r) return ; now->Mid = l + r >> 1; Build (now->Left, l, now->Mid); Build (now->Right, now->Mid + 1, r); } void Change_Section (Segment_Tree_Data *&now, int l, int r, int to) { if (l <= now->l && r >= now->r) { now->key = max (now->key, to); now->Flandre = max (now->Flandre, to); return ; } if (now->Flandre) { now->Left->key = max (now->Flandre, now->Left->key); now->Right->key = max (now->Flandre, now->Right->key); now->Left->Flandre = max (now->Flandre, now->Left->Flandre); now->Right->Flandre = max (now->Flandre, now->Right->Flandre); now->Flandre = 0; } if (l <= now->Mid) Change_Section (now->Left, l, min (now->Mid, r), to); if (r > now->Mid) Change_Section (now->Right, max (now->Mid + 1, l), r, to); now->key = max (now->Left->key, now->Right->key); } int Query (Segment_Tree_Data *&now, int pos) { if (now->l == now->r) return now->key; if (now->Flandre) { now->Left->key = max (now->Flandre, now->Left->key); now->Right->key = max (now->Flandre, now->Right->key); now->Left->Flandre = max (now->Flandre, now->Left->Flandre); now->Right->Flandre = max (now->Flandre, now->Right->Flandre); now->Flandre = 0; } now->key = max (now->Left->key, now->Right->key); if (pos <= now->Mid) return Query (now->Left, pos); else return Query (now->Right, pos); } }; Segment_Tree_Type Tree; Data_Type data[Max]; int Answer; int rank[Max << 2]; int N; int Size, Count; Point_Data point[Max]; int main (int argc, char *argv[]) { read (N); for (int i = 1; i <= N; i++) { read (data[i].h); read (data[i].l); read (data[i].r); rank[++Size] = data[i].l; rank[++Size] = data[i].r; } std :: sort (rank + 1, rank + 1 + Size); Size = std :: unique (rank + 1, rank + 1 + Size) - rank - 1; Root = NULL; Tree.Build (Root, 1, Size); for (int i = 1; i <= N; i++) { data[i].l = std :: lower_bound (rank + 1, rank + 1 + Size, data[i].l) - rank; data[i].r = std :: lower_bound (rank + 1, rank + 1 + Size, data[i].r) - rank; Tree.Change_Section (Root, data[i].l, data[i].r - 1, data[i].h); } for (int i = 1; i <= Size; i++) { point[i].x = rank[i]; point[i].y = Tree.Query (Root, i); if (point[i].y != point[i - 1].y) Answer++; } printf ("%d\n", Answer << 1); for (int i = 1; i <= Size; i++) if (point[i].y != point[i - 1].y) { printf ("%d %d\n", point[i].x, point[i - 1].y); printf ("%d %d\n", point[i].x, point[i].y); } return 0; }
时间: 2024-12-28 16:04:37