zoukankan      html  css  js  c++  java
  • poj 1177 Picture

    http://poj.org/problem?id=1177

      经典线段树,求矩形并的周长。把坐标排个序,然后插入线段树,求其变化的和就可以了。轻松1y~

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <vector>
      4 
      5 using namespace std;
      6 
      7 #define lson l, m, rt << 1
      8 #define rson m + 1, r, rt << 1 | 1
      9 #define root -10001, 10001, 1
     10 
     11 const int maxn = 40005;
     12 struct segTree{
     13     int sum[maxn << 2], low[maxn << 2], high[maxn << 2], late[maxn << 2];
     14 
     15     void up(int rt) {
     16         int ls = rt << 1, rs = rt << 1 | 1;
     17 
     18         sum[rt] = sum[ls] + sum[rs];
     19         low[rt] = min(low[ls], low[rs]);
     20         high[rt] = max(high[ls], high[rs]);
     21     }
     22     void down(int rt) {
     23         if (late[rt]) {
     24             int ls = rt << 1, rs = rt << 1 | 1;
     25 
     26             late[ls] += late[rt];
     27             late[rs] += late[rt];
     28             low[ls] += late[rt];
     29             low[rs] += late[rt];
     30             high[ls] += late[rt];
     31             high[rs] += late[rt];
     32             late[rt] = 0;
     33         }
     34     }
     35     void build(int l, int r, int rt) {
     36         sum[rt] = low[rt] = high[rt] = late[rt] = 0;
     37         if (l == r) {
     38             return ;
     39         }
     40         int m = (l + r) >> 1;
     41         build(lson);
     42         build(rson);
     43     }
     44     void fix(int l, int r, int rt) {
     45         if (l == r || !high[rt] || low[rt]) {
     46             if (low[rt]) {
     47                 sum[rt] = r - l + 1;
     48             } else if (!high[rt]) {
     49                 sum[rt] = 0;
     50             }
     51             return ;
     52         }
     53         int m = (l + r) >> 1;
     54         down(rt);
     55         fix(lson);
     56         fix(rson);
     57         up(rt);
     58     }
     59     void update(int L, int R, int d, int l, int r, int rt) {
     60         if (L <= l && r <= R) {
     61             low[rt] += d;
     62             high[rt] += d;
     63             late[rt] += d;
     64             if (low[rt]) {
     65                 sum[rt] = r - l + 1;
     66             } else if (!high[rt]) {
     67                 sum[rt] = 0;
     68             } else {
     69                 fix(l, r, rt);
     70             }
     71             return ;
     72         }
     73         int m = (l + r) >> 1;
     74         down(rt);
     75         if (L <= m) update(L, R, d, lson);
     76         if (m < R) update(L, R, d, rson);
     77         up(rt);
     78     }
     79     int query() {
     80         fix(root);
     81         return sum[1];
     82     }
     83 } segT;
     84 
     85 struct Rect {
     86     int x1, y1;
     87     int x2, y2;
     88 } ;
     89 vector<Rect> rect;
     90 
     91 void input(int n) {
     92     Rect buf;
     93 
     94     rect.clear();
     95     while (n--) {
     96         scanf("%d%d%d%d", &buf.x1, &buf.y1, &buf.x2, &buf.y2);
     97         if (buf.x1 > buf.x2) swap(buf.x1, buf.x2);
     98         if (buf.y1 > buf.y2) swap(buf.y1, buf.y2);
     99         rect.push_back(buf);
    100         swap(buf.x1, buf.x2);
    101         swap(buf.y1, buf.y2);
    102         rect.push_back(buf);
    103     }
    104 }
    105 
    106 bool cmpx(Rect a, Rect b) {
    107     return a.x1 < b.x1;
    108 }
    109 
    110 bool cmpy(Rect a, Rect b) {
    111     return a.y1 < b.y1;
    112 }
    113 
    114 int deal() {
    115     int last = 0, ret = 0;
    116     vector<Rect>::iterator ii;
    117     // cal x
    118     sort(rect.begin(), rect.end(), cmpx);
    119     segT.build(root);
    120     for (ii = rect.begin(); ii != rect.end(); ii++) {
    121         int y1 = (*ii).y1, y2 = (*ii).y2;
    122         if (y1 < y2) {
    123             segT.update(y1, y2 - 1, 1, root);
    124             ret += segT.query() - last;
    125         } else {
    126             segT.update(y2, y1 - 1, -1, root);
    127             ret += last - segT.query();
    128         }
    129         last = segT.query();
    130 //        printf("y %d %d %d\n", last, y1, y2);
    131     }
    132     // cal y
    133     last = 0;
    134     sort(rect.begin(), rect.end(), cmpy);
    135     segT.build(root);
    136     for (ii = rect.begin(); ii != rect.end(); ii++) {
    137         int x1 = (*ii).x1, x2 = (*ii).x2;
    138         if (x1 < x2) {
    139             segT.update(x1, x2 - 1, 1, root);
    140             ret += segT.query() - last;
    141         } else {
    142             segT.update(x2, x1 - 1, -1, root);
    143             ret += last - segT.query();
    144         }
    145         last = segT.query();
    146 //        printf("x %d %d %d\n", last, x1, x2);
    147     }
    148 
    149     return ret;
    150 }
    151 
    152 int main() {
    153     int n;
    154 
    155 //    freopen("in", "r", stdin);
    156     while (~scanf("%d", &n)) {
    157         input(n);
    158         printf("%d\n", deal());
    159     }
    160 
    161     return 0;
    162 }

    UPD:

      之前没看懂这道题的正确做法,然后被我yy了一个只是用线段树优化的代码,并没有起到线段树的真正作用。现在补上最新的,用线段树完美维护的代码,16ms通过。

    View Code
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 
     6 using namespace std;
     7 
     8 #define _clr(x) memset(x, 0, sizeof(x))
     9 #define REP(i, n) for (int i = 0; i < (n); i++)
    10 #define REP_1(i, n) for (int i = 1; i <= (n); i++)
    11 
    12 struct Side {
    13     int x1, x2, y, d;
    14     Side() {}
    15     Side(int _x1, int _x2, int _y, int _d) : x1(_x1), x2(_x2), y(_y), d(_d) {}
    16 } x[11111], y[11111];
    17 
    18 bool cmp(Side a, Side b) {
    19     if (a.y != b.y) return a.y < b.y;
    20     return a.d > b.d;
    21 }
    22 
    23 void input(int n) {
    24     int x1, y1, x2, y2;
    25     REP(i, n) {
    26         scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    27         if (x1 > x2) swap(x1, x2);
    28         if (y1 > y2) swap(y1, y2);
    29         x[i << 1] = Side(x1, x2 - 1, y1, 1);
    30         x[i << 1 | 1] = Side(x1, x2 - 1, y2, -1);
    31         y[i << 1] = Side(y1, y2 - 1, x1, 1);
    32         y[i << 1 | 1] = Side(y1, y2 - 1, x2, -1);
    33     }
    34     sort(x, x + (n << 1), cmp);
    35     sort(y, y + (n << 1), cmp);
    36 }
    37 
    38 const int N = 22222;
    39 int sum[N << 2], cnt[N << 2];
    40 
    41 #define lson l, m, rt << 1
    42 #define rson m + 1, r, rt << 1 | 1
    43 #define ROOT -10010, 10010, 1
    44 
    45 void up(int rt, int len) {
    46     if (cnt[rt]) {
    47         sum[rt] = len;
    48     } else {
    49         sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    50     }
    51 }
    52 
    53 void build(int l, int r, int rt) {
    54     sum[rt] = cnt[rt] = 0;
    55     if (l == r) return ;
    56     int m = (l + r) >> 1;
    57     build(lson);
    58     build(rson);
    59 }
    60 
    61 void update(int L, int R, int d, int l, int r, int rt) {
    62     if (L <= l && r <= R) {
    63         cnt[rt] += d;
    64         up(rt, r - l + 1);
    65         return ;
    66     }
    67     int m = (l + r) >> 1;
    68     if (L <= m) update(L, R, d, lson);
    69     if (m < R) update(L, R, d, rson);
    70     up(rt, r - l + 1);
    71 }
    72 
    73 int sweepLine(Side *s, int n) {
    74     n <<= 1;
    75     int ret = 0, cur = 0;
    76     build(ROOT);
    77     REP(i, n) {
    78         update(s[i].x1, s[i].x2, s[i].d, ROOT);
    79         ret += abs(cur - sum[1]);
    80         cur = sum[1];
    81     }
    82     return ret;
    83 }
    84 
    85 int main() {
    86 //    freopen("in", "r", stdin);
    87     int n;
    88     while (~scanf("%d", &n)) {
    89         input(n);
    90         printf("%d\n", sweepLine(x, n) + sweepLine(y, n));
    91     }
    92     return 0;
    93 }

      这个代码里面,就算是成段操作,也不用将结果推倒儿子节点处。这样一来就可以实现返回历史历史状态的效果了。

    ——written by Lyon

  • 相关阅读:
    c#连接MySQL数据库
    MySQL下载与安装
    python简单页面爬虫入门 BeautifulSoup实现
    vue打包后.woff字体文件路径问题处理
    ReactNative真机运行
    前端知识总结--性能优化
    前端知识总结--ES6新特性
    我的开发框架(WinForm)4
    我的开发框架(WinForm)3
    我的开发框架(WinForm)2
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_1177_Lyon.html
Copyright © 2011-2022 走看看