首页 > 代码库 > [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(扫描线,线段树,矩形并周长)