[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(扫描线,线段树,矩形并周长)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 1828 Picture(线段树,扫描线)

HDU1828 Picture 线段树+扫描线模板题

HDU 1828 Picture(线段树扫描线求周长)

hdu1828 Picture (线段树:扫描线周长)

51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

HDU-1828-Picture(线段树)