I was solving one of the problem in USACO 2007 Open Silver. The problem is as follows:
Description
Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city hosrizon 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? Thanks!
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define INF 1000000000
enum {MAX = 2, DIM = 3};
typedef struct Outline Outline;
struct Outline {
long long pos;
long long 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;
}
void error(const char *message) {
fprintf(stderr, "%s\n", message);
abort();
}
int main()
{
int num;
Outline **p, *cp;
scanf("%d", &num);
p = (Outline **) malloc(num * sizeof(Outline *));
for (int i = 0; i < num; i++) {
p[i] = (Outline *) malloc(DIM * sizeof(Outline));
long long lef, rig, mid;
if (p[i] == NULL) error("out of memory");
scanf("%lld %lld %lld", &lef, &rig, &mid);
p[i][0].pos = lef;
p[i][0].height = mid;
p[i][1].pos = rig;
p[i][1].height = 0;
p[i][2].pos = INF;
}
cp = recursive(p, 0, num-1);
free(p);
long long 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("%lld\n", square);
free(cp);
return 0;
}