POJ3277:City Horizon

——problem:求平面上矩形的面积,重复的只算一次。矩形的一边和X轴重合。

——solution:离散化+线段树

——url:http://poj.org/problem?id=3277

比赛的时候先离散化试了下,超时。于是只能再写线段树,结果线段树写撮了。

注意:

1、40000个矩形,边大概有80000多个,线段树的数组至少要开到80000×3=240000。

2、所有矩形先按从小到大排序。这样插入的时候不必判断已经插入矩形的高度,直接插就可以了。

3、注意面积会超过int的范围,要开long long。

代码:

第一个代码矩形没有排序。

于是node有三个域,h记录高度(如果左右子树的高度不同则为-1),s记录面积,flag记录是否有懒人标签。

第二个代码矩形按照从小到大排序。

此时发现h域可以省略,只要在打标签的时候记录下高度就可以了,于是把flag和h合并成一个。

View Code
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<memory.h>
4  #define N 100000
5  int i, j, l, r, num, n;
6  long long x[N];
7  long long ans;
8  struct Tnode
9 {
10 long long s, h;
11 bool flag;
12 } T[800000];
13 struct node
14 {
15 long long a, b, h;
16 } build[40004];
17 long long max(long long a, long long b)
18 {
19 return a > b ? a : b;
20 }
21 int cmp(const void *a, const void *b)
22 {
23 return *(long long *) a - *(long long *) b;
24 }
25 int binary_search(long long u)
26 {
27 int l = 0, r = num, mid;
28 while (l <= r)
29 {
30 mid = (l + r) / 2;
31 if (x[mid] > u)
32 r = mid - 1;
33 if (x[mid] < u)
34 l = mid + 1;
35 if (x[mid] == u)
36 return mid;
37 }
38 }
39 void update(int left, int right, int num)
40 {
41 int mid;
42 if (left == right - 1)
43 return;
44 mid = (left + right) / 2;
45 if (T[num].flag)
46 {
47 T[num].flag = false;
48 T[num * 2].h = T[num].h;
49 T[num * 2].flag = true;
50 T[num * 2].s = (x[mid] - x[left]) * T[num * 2].h;
51 T[num * 2 + 1].h = T[num].h;
52 T[num * 2 + 1].s = (x[right] - x[mid]) * T[num * 2 + 1].h;
53 T[num * 2 + 1].flag = true;
54 }
55 }
56 void tree_insert(int left, int right, int l, int r, long long height, int num)
57 {
58 int mid;
59 if (left >= right)
60 return;
61 if (left == right - 1)
62 {
63 T[num].h = max(T[num].h, height);
64 T[num].s = T[num].h * (x[r] - x[l]);
65 return;
66 }
67 update(left, right, num);
68 if (left == l && right == r && T[num].h != -1 && height > T[num].h)
69 {
70 T[num].flag = true;
71 T[num].h = height;
72 T[num].s = (x[r] - x[l]) * T[num].h;
73 return;
74 }
75 mid = (left + right) / 2;
76 if (T[num].h == -1 || height > T[num].h)
77 {
78 if (mid >= r)
79 {
80 tree_insert(left, mid, l, r, height, num * 2);
81 }
82 else if (mid <= l)
83 {
84 tree_insert(mid, right, l, r, height, num * 2 + 1);
85 }
86 else
87 {
88 tree_insert(left, mid, l, mid, height, num * 2);
89 tree_insert(mid, right, mid, r, height, num * 2 + 1);
90 }
91 }
92 T[num].s = T[num * 2].s + T[num * 2 + 1].s;
93 if (T[num * 2].h != T[num * 2 + 1].h || T[num * 2 + 1].h == -1
94 || T[num * 2].h == -1)
95 T[num].h = -1;
96 else
97 T[num].h = T[num * 2].h;
98 }
99 int main()
100 {
101 scanf("%d", &n);
102 memset(T, 0, sizeof(T));
103 x[0] = 0;
104 num = 0;
105 for (i = 0; i < n; i++)
106 {
107 scanf("%lld%lld%lld", &build[i].a, &build[i].b, &build[i].h);
108 num += 2;
109 x[num - 1] = build[i].a;
110 x[num] = build[i].b;
111 }
112 qsort(x, num + 1, sizeof(x[0]), cmp);
113 j = 0;
114 for (i = 0; i <= num; i++)
115 if (x[i] != x[j])
116 x[++j] = x[i];
117 num = j;
118 for (i = 0; i < n; i++)
119 {
120 l = binary_search(build[i].a);
121 r = binary_search(build[i].b);
122 tree_insert(0, num, l, r, build[i].h, 1);
123 }
124 printf("%lld\n", T[1].s);
125 return 0;
126 }
View Code
#include<stdio.h>
#include
<stdlib.h>
#include
<memory.h>
#define N 80010
int i, j, l, r, num, n;
long long x[N];
long long ans;
struct Tnode
{
long long s, flag;
} T[
260000];
struct node
{
long long a, b, h;
} build[
40004];
int cmp1(const void *a, const void *b)
{
return *(long long *) a - *(long long *) b;
}
int cmp2(const void *a, const void *b)
{
return (*(node *) a).h - (*(node *) b).h;
}
int binary_search(long long u)
{
int l = 0, r = num, mid;
while (l <= r)
{
mid
= (l + r) / 2;
if (x[mid] > u)
r
= mid - 1;
if (x[mid] < u)
l
= mid + 1;
if (x[mid] == u)
return mid;
}
}
void update(int left, int right, int num) //更新标签
{
int mid;
if (left == right - 1)
return;
mid
= (left + right) / 2;
if (T[num].flag > 0)
{
T[num
* 2].flag = T[num].flag;
T[num
* 2].s = (x[mid] - x[left]) * T[num].flag;
T[num
* 2 + 1].s = (x[right] - x[mid]) * T[num].flag;
T[num
* 2 + 1].flag = T[num].flag;
T[num].flag
= 0;
}
}
void tree_insert(int left, int right, int l, int r, long long height, int num)
{
int mid;
if (left >= right)
return;
if (left == right - 1)
{
T[num].s
= height * (x[r] - x[l]);
return;
}
update(left, right, num);
if (left == l && right == r) //懒人标签
{
T[num].flag
= height;
T[num].s
= (x[r] - x[l]) * height;
return;
}
mid
= (left + right) / 2;
if (mid >= r)
{
tree_insert(left, mid, l, r, height, num
* 2);
}
else if (mid <= l)
{
tree_insert(mid, right, l, r, height, num
* 2 + 1);
}
else
{
tree_insert(left, mid, l, mid, height, num
* 2);
tree_insert(mid, right, mid, r, height, num
* 2 + 1);
}
T[num].s
= T[num * 2].s + T[num * 2 + 1].s;
}
int main()
{
scanf(
"%d", &n);
memset(T,
0, sizeof(T));
x[
0] = 0;
num
= 0;
for (i = 0; i < n; i++)
{
scanf(
"%lld%lld%lld", &build[i].a, &build[i].b, &build[i].h);
num
+= 2;
x[num
- 1] = build[i].a;
x[num]
= build[i].b;
}
qsort(x, num
+ 1, sizeof(x[0]), cmp1);
qsort(build, n,
sizeof(build[0]), cmp2);
j
= 0;
for (i = 0; i <= num; i++)
if (x[i] != x[j])
x[
++j] = x[i];
for (i = 0; i < n; i++)
{
l
= binary_search(build[i].a);
r
= binary_search(build[i].b);
tree_insert(
0, num, l, r, build[i].h, 1);
}
printf(
"%lld\n", T[1].s);
return 0;
}
posted on 2011-04-02 21:39  风也轻云也淡  阅读(299)  评论(0编辑  收藏  举报