• [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 }
  • 相关阅读:
    electron 显示对话框 showMessageBoxSync showMessageBox
    c++ 随机数 取值范围 多线程
    c++ 字符串转换为数字
    VS2019 C++动态链接库的创建使用(1)
    js mutationobserver property vs attribute
    Chromium base 基础库概览
    Git:合并分支----git merge命令应用的三种情景
    chromium 处理 addEventListener 事件
    JavaScript监听属性改变
    chrome 启动开关参数
  • 原文地址:https://www.cnblogs.com/kirai/p/6809700.html
Copyright © 2020-2023  润新知