I was solving one of the problem in USACO 2007 Open Silver:
Description
Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.
The entire horizon is represented by a number line with \$N (1 ≤ N ≤ 40,000\$) buildings. Building \$i\$'s silhouette has a base that spans locations \$Ai\$ through \$Bi\$ along the horizon \$1 ≤ Ai < Bi ≤ 1,000,000,000\$ and has height \$Hi\$ (\$1 ≤ Hi ≤ 1,000,000,000\$).
Determine the area, in square units, of the aggregate silhouette formed by all \$N\$ buildings.
Input
- Line 1: A single integer: N
- Lines 2...N+1: Input line i+1 describes building \$i\$ with three space-separated integers: \$Ai\$, \$Bi\$, and \$Hi\$.
Output
Line 1: The total area, in square units, of the silhouettes formed by all \$N\$ buildings
Sample Input
4 2 5 1 9 10 4 6 8 2 4 6 3
Sample Output
16
I used a divide-and-conquer algorithm to solve this problem, but failed. The feedback of the online judgement system is Time Limit Exceeded. Could you help me to make my code more efficient, readable, and clear?
#include <stdio.h>
#include <malloc.h>
#define INF 10000000000
enum {MAX = 2, DIM = 3};
typedef struct Outline Outline;
struct Outline {
int pos;
int height;
};
/* merge two outlines of buildings */
Outline *mergebuilding(Outline *a, Outline *b, int num)
{
int a_move = 0;
int b_move = 0;
int r_count = 0;
int r_move = 0;
int pre = -1;
int x = 0;
int y = 0;
Outline *r = (Outline *) malloc(MAX * num * (sizeof(Outline)) + sizeof(Outline));
while (a[a_move].pos < INF || b[b_move].pos < INF) {
r[r_move].pos = (a[a_move].pos <= b[b_move].pos) ? a[a_move].pos : b[b_move].pos;
if (r[r_move].pos == a[a_move].pos) {
x = a[a_move].height;
a_move++;
}
if (r[r_move].pos == b[b_move].pos) {
y = b[b_move].height;
b_move++;
}
r[r_move].height = (x >= y) ? x : y;
if (r[r_move].height != pre) {
pre = r[r_move].height;
r[r_move+1] = r[r_move];
r_move++;
}
}
r[r_move].pos = INF;
return r;
}
/* divide-and-conquer */
Outline *recursive(Outline **p, int low, int high)
{
/*
Recursively divide the set of buildings into two parts
until one block, then merge two blocks from the bottom to the top.
*/
Outline *part1, *part2, *merge;
int mid;
if (low == high)
return p[low];
mid = (low + high) / 2;
part1 = recursive(p, low, mid);
part2 = recursive(p, mid+1, high);
merge = mergebuilding(part1, part2, low+high+1);
free(part1);
free(part2);
return merge;
}
int main()
{
int **bul;
int num;
Outline **p, *cp;
scanf("%d", &num);
bul = (int **) malloc(num * sizeof(int));
p = (Outline **) malloc(num * sizeof(Outline));
for (int i = 0; i < num; i++) {
bul[i] = (int *) malloc(DIM * sizeof(int));
p[i] = (Outline *) malloc(DIM * sizeof(Outline));
scanf("%d %d %d", &bul[i][0], &bul[i][1], &bul[i][2]);
p[i][0].pos = bul[i][0];
p[i][0].height = bul[i][2];
p[i][1].pos = bul[i][1];
p[i][1].height = 0;
p[i][2].pos = INF;
free(bul[i]);
}
free(bul);
cp = recursive(p, 0, num-1);
free(p);
int temp, square;
square = 0;
for (int i = 0; cp[i].pos < INF; i++) {
temp = (cp[i+1].pos - cp[i].pos) * cp[i].height;
square += temp;
}
printf("%d\n", square);
free(cp);
return 0;
}