[HDOJ1828]Picture(扫描线,线段树,矩形并周长)
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDOJ1828]Picture(扫描线,线段树,矩形并周长)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828
题意:求矩形并的周长。
很好发现一个规律,那就是扫描到当前状态,update之后的线段树中线段的长度减去update之前的长度差的绝对值恰好是当前段并后的水平或者垂直的线段长度。
那么。。存两棵线段树,横着扫一遍竖着扫一遍,加起来就行了。。
竟然没MLE。。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define lrt rt << 1 5 #define rrt rt << 1 | 1 6 const int maxn = 5500; 7 typedef struct Event { 8 double l, r, hx; 9 int sign; 10 }Event; 11 typedef struct Seg { 12 double len; 13 int sign; 14 }Seg; 15 16 vector<Event> event1, event2; 17 double hx[maxn<<1], hy[maxn<<1]; 18 Seg seg[maxn<<2]; 19 int hxcnt, hycnt; 20 int n; 21 22 bool cmp(Event a, Event b) { 23 if(a.hx != b.hx) return a.hx < b.hx; 24 return a.sign > b.sign; 25 } 26 27 int xid(double x) { 28 return lower_bound(hx, hx+hxcnt, x) - hx + 1; 29 } 30 31 int yid(double y) { 32 return lower_bound(hy, hy+hycnt, y) - hy + 1; 33 } 34 35 void build(int l, int r, int rt) { 36 seg[rt].len = .0; seg[rt].sign = 0; 37 if(l == r) return; 38 int mid = (l + r) >> 1; 39 build(l, mid, lrt); 40 build(mid+1, r, rrt); 41 } 42 43 void pushup(int l, int r, int rt) { 44 if(seg[rt].sign) seg[rt].len = hx[r] - hx[l-1]; 45 else { 46 if(l == r) seg[rt].len = .0; 47 else seg[rt].len = seg[lrt].len + seg[rrt].len; 48 } 49 } 50 51 void pushup1(int l, int r, int rt) { 52 if(seg[rt].sign) seg[rt].len = hy[r] - hy[l-1]; 53 else { 54 if(l == r) seg[rt].len = .0; 55 else seg[rt].len = seg[lrt].len + seg[rrt].len; 56 } 57 } 58 59 void update(bool flag, int L, int R, int sign, int l, int r, int rt) { 60 if(L <= l && r <= R) { 61 seg[rt].sign += sign; 62 if(!flag) pushup(l, r, rt); 63 else pushup1(l, r, rt); 64 return; 65 } 66 int mid = (l + r) >> 1; 67 if(L <= mid) update(flag, L, R, sign, l, mid, lrt); 68 if(mid < R) update(flag, L, R, sign, mid+1, r, rrt); 69 if(!flag) pushup(l, r, rt); 70 else pushup1(l, r, rt); 71 } 72 73 int main() { 74 // freopen("in", "r", stdin); 75 int _ = 1; 76 double ax, ay, bx, by; 77 while(~scanf("%d",&n)) { 78 hxcnt = 0; event1.clear(); event2.clear(); 79 for(int i = 0; i < n; i++) { 80 scanf("%lf%lf%lf%lf",&ax,&ay,&bx,&by); 81 event1.push_back({ax, bx, ay, 1}); 82 event1.push_back({ax, bx, by, -1}); 83 event2.push_back({ay, by, ax, 1}); 84 event2.push_back({ay, by, bx, -1}); 85 hx[hxcnt++] = ax; hx[hxcnt++] = bx; 86 hy[hycnt++] = ay; hy[hycnt++] = by; 87 } 88 sort(event1.begin(), event1.end(), cmp); 89 sort(event2.begin(), event2.end(), cmp); 90 sort(hx, hx+hxcnt); hxcnt = unique(hx, hx+hxcnt) - hx; 91 sort(hy, hy+hycnt); hycnt = unique(hy, hy+hycnt) - hy; 92 build(1, hxcnt, 1); 93 double ret = .0; 94 double pre = .0; 95 for(int i = 0; i < event1.size(); i++) { 96 int l = xid(event1[i].l); 97 int r = xid(event1[i].r) - 1; 98 int sign = event1[i].sign; 99 update(0, l, r, sign, 1, hxcnt, 1); 100 ret += abs(seg[1].len - pre); 101 pre = seg[1].len; 102 } 103 event1.clear(); 104 build(1, hycnt, 1); 105 pre = .0; 106 for(int i = 0; i < event2.size(); i++) { 107 int l = yid(event2[i].l); 108 int r = yid(event2[i].r) - 1; 109 int sign = event2[i].sign; 110 update(1, l, r, sign, 1, hycnt, 1); 111 ret += abs(seg[1].len - pre); 112 pre = seg[1].len; 113 } 114 cout << ret << endl; 115 } 116 return 0; 117 }
以上是关于[HDOJ1828]Picture(扫描线,线段树,矩形并周长)的主要内容,如果未能解决你的问题,请参考以下文章