综教楼后的那个坑

描述

  在 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. 3↵
  2. 4 2↵
  3. 2 7↵
  4. 6 4↵
以文本方式显示
  1. 4↵
  2. 50↵
  3. 26↵
1秒1024KB0
测试用例 12以文本方式显示
  1. 3↵
  2. 4 2↵
  3. 6 4↵
  4. 2 7↵
以文本方式显示
  1. 4↵
  2. 18↵
  3. 50↵
1秒1024KB0

思路:

        画图考虑情况,注意填满之后需要重新择定最低处,将已经填好的地方和旁边等高的合并

代码如下:

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值