GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版
还是使用算法竞赛入门经典书中的方式,O(n)的时间即可得到结果。但书中写的并不清楚,他只说了往左延伸和右延伸。
实际上需要遍历两次,第一次是从左到右,第二次从右到左。从左到右的时候,第一个元素直接设置为最高水位(天花板)。遍历时,当前元素只考虑前一个元素对其造成的影响。我选择了分每一种细节情况讨论,即前一个天花板地板,当前天花板地板的不同位置关系下,以及前一个水位是多少时,当前水位应该是多少。
从右到左遍历时也是一样,考虑后一个元素对当前元素的影响,分每种情况细节讨论。但是这里要简单一些,因为后一个水位不会比当前水位高(我们左侧遍历时考虑了这一点),因此只需要考虑后一个元素水位更低的场景。
AC代码
cpp
#include <stdio.h>
#define MAXN 1000005
int arrFloor[MAXN]; // 地板
int arrCeiling[MAXN]; // 天花板
int arrValue[MAXN]; // 当前水位
int n;
void computedFront()
{
int i;
arrValue[0] = arrCeiling[0];
for (i = 1; i < n; ++i)
{
if (arrCeiling[i] <= arrFloor[i - 1])
{
arrValue[i] = arrCeiling[i];
continue;
}
if (arrCeiling[i] >= arrFloor[i - 1] && arrCeiling[i] <= arrCeiling[i - 1] && arrFloor[i] <= arrFloor[i - 1])
{
if (arrCeiling[i] <= arrValue[i - 1])
arrValue[i] = arrCeiling[i];
else
arrValue[i] = arrValue[i - 1];
continue;
}
if (arrCeiling[i] <= arrCeiling[i - 1] && arrFloor[i] >= arrFloor[i - 1])
{
if (arrCeiling[i] <= arrValue[i - 1])
arrValue[i] = arrCeiling[i];
else if (arrFloor[i] <= arrValue[i - 1])
arrValue[i] = arrValue[i - 1];
else
arrValue[i] = arrFloor[i];
continue;
}
if (arrCeiling[i] >= arrCeiling[i - 1] && arrFloor[i] >= arrFloor[i - 1] && arrFloor[i] <= arrCeiling[i - 1])
{
if (arrFloor[i] <= arrValue[i - 1])
arrValue[i] = arrValue[i - 1];
else
arrValue[i] = arrFloor[i];
continue;
}
if (arrFloor[i] >= arrCeiling[i - 1])
{
arrValue[i] = arrFloor[i];
continue;
}
if (arrFloor[i] <= arrFloor[i - 1] && arrCeiling[i] >= arrCeiling[i - 1])
{
if (arrFloor[i] <= arrValue[i - 1])
arrValue[i] = arrValue[i - 1];
else
arrValue[i] = arrFloor[i];
continue;
}
// arrValue[i] = arrValue[i - 1];
}
}
void computedBack()
{
int i;
for (i = n - 2; i >= 0; --i)
{
if (arrCeiling[i] <= arrFloor[i + 1])
continue;
if (arrCeiling[i] >= arrFloor[i + 1] && arrCeiling[i] <= arrCeiling[i + 1] && arrFloor[i] <= arrFloor[i + 1])
{
if (arrValue[i + 1] <= arrValue[i])
arrValue[i] = arrValue[i + 1];
continue;
}
if (arrCeiling[i] <= arrCeiling[i + 1] && arrFloor[i] >= arrFloor[i + 1])
{
if (arrValue[i + 1] <= arrValue[i])
arrValue[i] = arrValue[i + 1] > arrFloor[i] ? arrValue[i + 1] : arrFloor[i];
continue;
}
if (arrCeiling[i] >= arrCeiling[i + 1] && arrFloor[i] >= arrFloor[i + 1] && arrFloor[i] <= arrCeiling[i + 1])
{
if (arrValue[i + 1] <= arrValue[i])
arrValue[i] = arrValue[i + 1] > arrFloor[i] ? arrValue[i + 1] : arrFloor[i];
continue;
}
if (arrFloor[i] >= arrCeiling[i + 1])
{
arrValue[i] = arrFloor[i];
continue;
}
if (arrFloor[i] <= arrFloor[i + 1] && arrCeiling[i] >= arrCeiling[i + 1])
{
if (arrValue[i + 1] <= arrValue[i])
arrValue[i] = arrValue[i + 1];
continue;
}
}
}
int main()
{
int z, i;
long long sum;
scanf("%d", &z);
while (z--)
{
scanf("%d", &n);
for (i = 0; i < n; ++i)
scanf("%d", &arrFloor[i]);
for (i = 0; i < n; ++i)
scanf("%d", &arrCeiling[i]);
computedFront();
computedBack();
sum = 0;
for (i = 0; i < n; ++i)
{
sum += arrValue[i] - arrFloor[i];
}
printf("%lld\n", sum);
}
return 0;
}