# Temple Offerings

Consider a devotee wishing to give offerings to temples along a mountain range. The temples are located in a row at different heights. Each temple should receive at least one offering. If two adjacent temples are at different altitudes, then the temple that is higher up should receive more offerings than the one that is lower down. If two adjacent temples are at the same height, then their offerings relative to each other does not matter. Given the number of temples and the heights of the temples in order, find the minimum number of offerings to bring.

Examples:

```Input  : 3
1 2 2
Output : 4
All temples must receive at-least one offering.
Now, the second temple is at a higher altitude
compared to the first one. Thus it receives one
extra offering.
The second temple and third temple are at the
same height, so we do not need to modify the
offerings. Offerings given are therefore: 1, 2,
1 giving a total of 4.

Input  : 6
1 4 3 6 2 1
Output : 10
We can distribute the offerings in the following
way, 1, 2, 1, 3, 2, 1. The second temple has to
receive more offerings than the first due to its
height being higher. The fourth must receive more
than the fifth, which in turn must receive more
than the sixth. Thus the total becomes 10.
```

## Recommended: Please solve it on “PRACTICE” first, before moving on to the solution.

We notice that each temple can either be above, below, or at the same level as the temple next to it. The offerings required at each temple is equal to the maximum length of the chain of temples at lower height as shown in the image.

Naive Approach
To follow the given rule, a temple must be offered at least x+1 where x is maximum of following two.

1. Number of temples on left in increasing order.
2. Number of temples on right in increasing order.

A naive method of solving this problem would be for each temple, go to the left until altitude increases, and do the same for the right.

```// Program to find minimum total offerings required
#include <iostream>
using namespace std;

// Returns minimum offerings required
int offeringNumber(int n, int templeHeight[])
{
int sum = 0;  // Initialize result

// Go through all templs one by one
for (int i = 0; i < n; ++i)
{
// Go to left while height keeps increasing
int left = 0, right = 0;
for (int j = i - 1; j >= 0; --j)
{
if (templeHeight[j] < templeHeight[j + 1])
++left;
else
break;
}

// Go to right while height keeps increasing
for (int j = i + 1; j < n; ++j)
{
if (templeHeight[j] < templeHeight[j - 1])
++right;
else
break;
}

// This temple should offer maximum of two
// values to follow the rule.
sum += max(right, left) + 1;
}

return sum;
}

// Driver code
int main()
{
int arr1[3] = {1, 2, 2};
cout << offeringNumber(3, arr1) << "\n";
int arr2[6] = {1, 4, 3, 6, 2, 1};
cout << offeringNumber(6, arr2) << "\n";
return 0;
}
```

Output:

```4
10
```

Time complexity: O(n2)
Space complexity: O(1)

Dynamic Programming Approach
By using Dynamic Programming, we can improve the time complexity. In this method, we create a structure of length n which maintains the maximum decreasing chain to the left of each temple and the maximum decreasing chain to the right of each temple. We go through once from 0 to N setting the value of left for each temple. We then go from N to 0 setting the value of right for each temple. We then compare the two and pick the maximum for each temple.

```// Program to find total offerings required
#include <iostream>
using namespace std;

// To store count of increasing order temples
// on left and right (including current temple)
struct Temple
{
int L;
int R;
};

// Returns count of minimum offerings for
// n temples of given heights.
int offeringNumber(int n, int templeHeight[])
{
// Initialize counts for all temples
Temple chainSize[n];
for (int i = 0; i < n; ++i)
{
chainSize[i].L = -1;
chainSize[i].R = -1;
}

// Values corner temples
chainSize[0].L = 1;
chainSize[n-1].R = 1;

// Filling left and right values using same
// values of previous(or next)
for (int i=1; i<n; ++i)
{
if (templeHeight[i - 1] < templeHeight[i])
chainSize[i].L = chainSize[i - 1].L + 1;
else
chainSize[i].L = 1;
}
for (int i=n-2; i>=0; --i)
{
if (templeHeight[i + 1] < templeHeight[i])
chainSize[i].R = chainSize[i + 1].R + 1;
else
chainSize[i].R = 1;
}

// Computing max of left and right for all
// temples and returing sum.
int sum = 0;
for (int i = 0; i < n; ++i)
sum += max(chainSize[i].L, chainSize[i].R);
return sum;
}

// Driver function
int main()
{
int arr1[3] = {1, 2, 2};
cout << offeringNumber(3, arr1) << "\n";
int arr2[6] = {1, 4, 3, 6, 2, 1};
cout << offeringNumber(6, arr2) << "\n";
return 0;
}
```

Output:

```4
10
```

Time complexity: O(n)
Space complexity: O(n)

# GATE CS Corner    Company Wise Coding Practice

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.
3.7 Average Difficulty : 3.7/5.0
Based on 13 vote(s)