首页 > 代码库 > [HDOJ1828]Picture(扫描线,线段树,矩形并周长)
[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(扫描线,线段树,矩形并周长)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。