• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

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

posted @ 2012-11-09 02:55  LyonLys  阅读(208)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3