描述
在 LIT 综教楼后有一个深坑,关于这个坑的来历,有很多种不同的说法。其中一种说法是,在很多年以前,这个坑就已经在那里了。这种说法也被大多数人认可,这是因为该坑有一种特别的结构,想要人工建造是有相当困难的。
从横截面图来看,坑底成阶梯状,由从左至右的 1..N 个的平面构成(其中 1 ≤ N ≤ 100,000),如图:
* * : * * : * * 8 * ** * 7 * ** * 6 * ** * 5 * ********* 4 <- 高度 * ********* 3 ************** 2 ************** 1 平面 | 1 |2| 3 |
每个平面 i 可以用两个数字来描述,即它的宽度 Wi 和高度 Hi,其中 1 ≤ Wi ≤ 1,000、1 ≤ Hi ≤ 1,000,000,而这个坑最特别的地方在于坑底每个平面的高度都是不同的。每到夏天,雨水会把坑填满,而在其它的季节,则需要通过人工灌水的方式把坑填满。灌水点设在坑底位置最低的那个平面,每分钟灌水量为一个单位(即高度和宽度均为 1)。随着水位的增长,水自然会向其它平面扩散,当水将某平面覆盖且水高达到一个单位时,就认为该平面被水覆盖了。
请你计算每个平面被水覆盖的时间。
灌水 水满后自动扩散 | | * | * * | * * * * V * * V * * * * * * .... * *~~~~~~~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~**~~~~~~* *~~~~**~~~~~~* * ********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* ************** ************** ************** ************** ************** ************** 4 分钟后 26 分钟后 50 分钟后 平面 1 被水覆盖 平面 3 被水覆盖 平面 2 被水覆盖输入
输入的第一行是一个整数 N,表示平面的数量。从第二行开始的 N 行上分别有两个整数,分别表示平面的宽度和高度。
输出
输出每个平面被水覆盖的时间。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB | 0 |
测试用例 12 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB | 0 |
思路:
画图考虑情况,注意填满之后需要重新择定最低处,将已经填好的地方和旁边等高的合并
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100010
typedef struct Hole
{
int ordinal;//平台序号
long long width;
int hight;
struct Hole *p;
struct Hole *next;
} hole;
long ans[MAX_SIZE];
void PourAndConnect(hole *);
int main()
{
long width, height;
int N;
scanf("%d", &N);
hole *fir = (hole *)calloc(1, sizeof(hole));
hole lwall = {0, 1000010, 0, NULL, fir};
hole rwall = {0, 1000010, 0, NULL, NULL};
hole *cur = fir, *pre = &lwall, *lowest = fir;
for (int i = 0; i < N; i++)
{
scanf("%ld %ld", &width, &height);
cur->width = width;
cur->hight = height;
cur->ordinal = i + 1;
if (height < lowest->hight)
lowest = cur;
cur->p = pre;
if (i == N - 1)
cur->next = &rwall;
else
cur->next = (hole *)calloc(1, sizeof(hole));
pre = cur;
cur = cur->next;
}
PourAndConnect(lowest);
for (int i = 0; i < N; i++)
printf("%ld\n", ans[i + 1]);
return 0;
}
void PourAndConnect(hole *lowest)//填坑并合并填好的平台,判断新的最低
{
long long time = 0;
while (lowest->p->width != 0 || lowest->next->width != 0)
{
ans[lowest->ordinal] = time + lowest->width;
hole *low = lowest->p->hight < lowest->next->hight ? lowest->p : lowest->next;
time += (low->hight - lowest->hight) * lowest->width;
low->width += lowest->width;
lowest->p->next = lowest->next;
lowest->next->p = lowest->p;
free(lowest);
lowest = low;
if (lowest->hight < lowest->p->hight && lowest->hight < lowest->next->hight)
continue;
else if (lowest->hight > lowest->p->hight)
while (lowest->hight > lowest->p->hight)
lowest = lowest->p;
else
while (lowest->hight > lowest->next->hight)
lowest = lowest->next;
}
ans[lowest->ordinal] = time + lowest->width;
}