573B. Bear and Blocks(Codeforces Round #318)

本文介绍了一道关于熊摧毁塔的算法题目,通过分析不同高度的塔被摧毁的过程,提出了解决方案。核心思路在于预处理序列,找到使得当前元素能够被完全移除所需的最小操作次数。
B. Bear and Blocks
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Limak is a little bear who loves to play. Today he is playing by destroying block towers. He built n towers in a row. The i-th tower is made of hi identical blocks. For clarification see picture for the first sample.

Limak will repeat the following operation till everything is destroyed.

Block is called internal if it has all four neighbors, i.e. it has each side (top, left, down and right) adjacent to other block or to the floor. Otherwise, block is boundary. In one operation Limak destroys all boundary blocks. His paws are very fast and he destroys all those blocks at the same time.

Limak is ready to start. You task is to count how many operations will it take him to destroy all towers.

Input

The first line contains single integer n (1 ≤ n ≤ 105).

The second line contains n space-separated integers h1, h2, ..., hn (1 ≤ hi ≤ 109) — sizes of towers.

Output

Print the number of operations needed to destroy all towers.

Sample test(s)
input
6
2 1 4 6 2 2
output
3
input
7
3 3 3 1 3 3 3
output
2
Note

The picture below shows all three operations for the first sample test. Each time boundary blocks are marked with red color.

After first operation there are four blocks left and only one remains after second operation. This last block is destroyed in third operation.



解题思路:

      假设只取序列的一段进行分析,a[i-1]>a[i]<a[i+1]<a[i+2]<a[i+3],且a[i]是可以操作a[i]次的,那a[i+1]是操作

a[i+1]次,在删除a[i]最上面那个格子的时候,可以把a[i+1]比a[i]多的那部分都删除,同理a[i+2]的操作次数就

是a[i]+2,还有一点需要考虑的是,在序列中间的部分元素是有可能进行a[i]次操作的,于是题目就转化找哪个这类元素到当前位置的操作数最少,有可能那个元素在当前值的前面也可能在后面,于是就考虑分两种情况预处理一下,先考虑那个元素在当前值的前方的时候,cur是前面可以取到a[cur]个操作的位置,当从那个位置到当前位置的操作数大于a[i](i为当前位置),这时候a[i]就可全部取到了。在后面也一样。最后再对每个位置考虑取前和后哪个更小就可以了,可以一列一列的删除的特殊考虑一下就可以了。


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100000+1000;
int a[maxn];
int b[maxn];
int c[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    int cur=1;
    b[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(a[cur]+i-cur<a[i])
        {
            b[i]=a[cur]+i-cur;
        }
        else
        {
            b[i]=a[i];
            cur=i;
        }
        b[i]=min(i,b[i]);
    }
    c[n]=1;
    cur=n;
    for(int i=n-1;i>0;i--)
    {
       if(a[cur]+cur-i<a[i])
       {
           c[i]=a[cur]+cur-i;
       }
       else
       {
       c[i]=a[i];
       cur=i;
       }
       c[i]=min(n+1-i,c[i]);
    }
    int ans=0,temp;
    for(int i=1;i<=n;i++)
    {
        temp=min(b[i],c[i]);
        ans=max(temp,ans);
    }
    cout<<ans<<endl;
    return 0;
}


<think>我们之前讨论了关于导入错误的问题,用户提到`fromnetworksimportblocks`报错,但使用`importnetworks.blocksasB`后不再报错。我们需要分析这种差异的原因并提供解决方案。回顾用户的问题:1.原始报错:`fromnetworksimportblocks`报错2.改用`importnetworks.blocksasB`成功分析:在Python中,这两种导入方式有所不同:-`fromnetworksimportblocks`:尝试从`networks`包中导入名为`blocks`的模块(或子模块)。这要求`networks`包中必须有一个名为`blocks`的模块(即`blocks.py`文件)或一个名为`blocks`的子包(包含`__init__.py`的目录),或者在`networks/__init__.py`中明确导入了`blocks`。-`importnetworks.blocksasB`:导入的是`networks`包下的`blocks`子模块,这种导入方式要求`blocks`是一个模块(文件)或包(目录),并且它位于`networks`目录下。为什么第一种方式失败而第二种成功?可能的原因:1.在`networks/__init__.py`文件中没有导入`blocks`模块。-当使用`fromnetworksimportblocks`时,如果`__init__.py`中没有显式导入`blocks`,那么解释器会尝试在`networks`目录下查找`blocks.py`或`blocks`子目录(包)。如果找到,则导入成功;否则失败。-而使用`importnetworks.blocks`时,解释器会直接去`networks`目录下查找`blocks`模块(即`blocks.py`文件)或`blocks`包,而不依赖于`__init__.py`的内容。2.另一种可能是`networks`包下的`blocks`模块是一个子包(即`blocks`是一个目录),而不是一个单独的`.py`文件。在这种情况下,使用`fromnetworksimportblocks`需要确保`blocks`子包被正确初始化(即包含`__init__.py`)。如果`blocks`子包中缺少`__init__.py`,那么它不会被识别为包的一部分,导致第一种导入方式失败。但是,第二种导入方式可能仍然成功,因为子包即使没有`__init__.py`(在Python3.3+中,称为命名空间包),也可以被导入。但是,为了兼容性,建议每个包都包含`__init__.py`。3.还有可能是由于循环导入或导入时机的问题,导致第一种方式在特定上下文中失败。解决方案:1.检查文件结构:```project/networks/__init__.py#必须存在blocks.py#如果blocks是模块,则需要这个文件#或者blocks/#如果blocks是子包,则需要这个目录__init__.py```2.如果`blocks`是一个模块(即`blocks.py`),那么在`networks/__init__.py`中,可以显式导入`blocks`模块,以支持第一种导入方式。例如,在`networks/__init__.py`中添加:```pythonfrom.importblocks```或者```pythonfrom.blocksimport*```这样,当导入`networks`包时,`blocks`模块就会作为包的一部分被导入,就可以使用`fromnetworksimportblocks`。3.如果用户不想修改`networks/__init__.py`,那么使用第二种导入方式(`importnetworks.blocksasB`)是更好的选择,因为它不依赖于`__init__.py`的内容。总结:两种导入方式在机制上有区别。第一种方式依赖包初始化时导入的符号,而第二种方式直接通过包路径查找模块。由于第二种方式成功,说明`blocks`模块确实存在于`networks`目录下。因此,用户可以选择:-修改`networks/__init__.py`来支持第一种导入方式(如果希望使用第一种)。-继续使用第二种导入方式(更直接,更推荐)。为了帮助用户理解,我们可以给出一个示例:假设目录结构如下:```project/main.pynetworks/__init__.py#空文件blocks.py```在`main.py`中:方式1(失败):由于`networks/__init__.py`是空的,所以`fromnetworksimportblocks`会尝试在`networks`包中寻找名为`blocks`的模块或子包,但解释器不会自动将`blocks.py`视为包的一部分(除非在`__init__.py`中导入)。因此,这个导入会失败。方式2(成功):`importnetworks.blocksasB`直接去`networks`目录下寻找`blocks.py`(或`blocks`子目录),找到后导入。解决方式1的导入失败:在`networks/__init__.py`中加入:from.importblocks这样,当导入`networks`包时,就会自动导入`blocks`模块,然后就可以使用`fromnetworksimportblocks`。注意:在Python中,包内的导入通常使用相对导入(在`__init__.py`中使用`from.importblocks`)。因此,用户可以根据自己的项目结构选择合适的方法。同时,我们也可以提醒用户检查是否有命名冲突,例如是否有名为`networks`的第三方模块已经安装在环境中。综上所述,我们给出解决方案:1.推荐使用`importnetworks.blocksasB`,因为它更直接,不依赖包初始化。2.如果希望使用`fromnetworksimportblocks`,则需要修改`networks/__init__.py`,添加对`blocks`模块的导入。如果用户仍然遇到问题,可以检查以下步骤:-确认`networks`目录下有`blocks.py`文件(或`blocks`子包)。-确认运行脚本的当前目录在项目根目录(或项目根目录在sys.path中)。-确认没有其他名为`networks`的模块干扰。最后,根据用户之前提到的,使用第二种方式(`importnetworks.blocksasB`)已经成功,所以如果用户没有特殊需求,可以继续使用这种方式。注:用户提到“加入#讲不再报错”,可能是用户注释掉了某些代码?但根据问题描述,我们主要关注两种导入方式的差异。生成相关问题:1.如何在Python包中组织模块以支持不同的导入方式?2.相对导入和绝对导入在Python中有什么区别?3.如何解决Python中的循环导入问题?4.在大型项目中如何管理模块导入以避免冲突?回答用户:</think> ### `from networks import blocks`报错原因及`import networks.blocks`成功的分析 #### 问题根源分析 根据您的描述,原始导入方式`from networks import blocks`报错,但改用`import networks.blocks as B`后问题解决,主要原因有: 1. **`__init__.py`未显式暴露模块** Python包中需要明确声明可导出的模块(PEP 420标准)[^1]。若`networks/__init__.py`中缺少: ```python from . import blocks # 关键声明 ``` 则`blocks.py`文件存在但不会暴露给外部调用者,导致`from networks import blocks`失败。 2. **绝对导入 vs 隐式相对导入** `from networks import blocks`依赖于`__init__.py`的显式导出,而`import networks.blocks`直接通过绝对路径访问模块文件,绕过`__init__.py`的限制[^2]。 3. **包结构不一致的补救措施** 当`networks/__init__.py`不完整时: ```mermaid graph TD A[from networks import blocks] -->|需__init__显式导出| B(失败) C[import networks.blocks] -->|直接访问文件路径| D(成功) ``` #### 永久解决方案 1. **完善包声明(推荐)** 在`networks/__init__.py`中添加: ```python from . import blocks # 声明可导出模块 __all__ = [&#39;blocks&#39;] # 显式定义导出对象 ``` 之后即可安全使用`from networks import blocks` 2. **验证包结构完整性** ```bash project/ ├── main.py └── networks/ ├── __init__.py # 必须包含上述声明 └── blocks.py # 模块文件 ``` 3. **环境路径确认** ```python # 检测包查找路径 import sys print(sys.path) # 确认项目根目录在列表中 ``` > 关键结论:**Python包的`__init__.py`控制模块暴露行为**。显式声明可避免导入歧义(尤其在卷积神经网络等复杂项目中)[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值