ccf-非零段划分-python题解

非零段划分

A1,A2,…,An是一个由 n 个自然数(非负整数)组成的数组。我们称其中 Ai,…,Aj 是一个非零段,当且仅当以下条件同时满足:
·1≤i≤j≤n;
·对于任意的整数 k,若 i≤k≤j,则 Ak>0;
·i=1 或 Ai-1=0;
·j=n 或 Aj+1=0。
下面展示了几个简单的例子:
·A = [3, 1, 2, 0, 0, 2, 0, 4, 5, 0, 2] 中的 4 个非零段依次为 [3, 1, 2]、[2]、[4, 5] 和 [2];
·A = [2, 3, 1, 4, 5] 仅有 1 个非零段;
·A = [0, 0, 0] 则不含非零段(即非零段个数为 0)。
现在我们可以对数组 A 进行如下操作:任选一个正整数 p,然后将 A 中所有小于 p 的数都变为 0。试选取一个合适的 p,使得数组 A 中的非零段个数达到最大。若输入的 A 所含非零段数已达最大值,可取 p = 1,即不对 A 做任何修改。

输入格式
从标准输入读入数据。

输入的第一行包含一个正整数 n。

输入的第二行包含 n 个用空格分隔的自然数 A1, A2, … , An。

输出格式
输出到标准输出。

仅输出一个整数,表示对数组 A 进行操作后,其非零段个数能达到的最大值。

样例1输入
11
3 1 2 0 0 2 0 4 5 0 2
样例1输出
5
样例1解释
p = 2 时,A = [3, 0, 2, 0, 0, 2, 0, 4, 5, 0, 2],5 个非零段依次为 [3]、[2]、[2]、[4, 5] 和 [2];此时非零段个数达到最大。

样例2输入
14
5 1 20 10 10 10 10 15 10 20 1 5 10 15
样例2输出
4
样例2解释
p = 12 时,A = [0, 0, 20, 0, 0, 0, 0, 15, 0, 20, 0, 0, 0, 15],4 个非零段依次为 [20]、[15]、[20] 和 [15];此时非零段个数达到最大。

样例3输入
3
1 0 0
样例3输出
1
样例3解释
p = 1 时,A = [1, 0, 0],此时仅有 1 个非零段 [1],非零段个数达到最大。

样例4输入
3
0 0 0
样例4输出
0
样例4解释
无论 p 取何值,A 都不含有非零段,故非零段个数至多为 0。

子任务
70% 的测试数据满足 n ≤ 1000;

全部的测试数据满足 n≤5×105,且数组 A 中的每一个数均不超过 104。
思路:类岛屿问题,采用逆向思路,下降到什么位置有岛屿漏出来。当某个点为凹点时岛屿数减一,为凸点时岛屿数加一。

n = int(input())
a = list(map(int,input().split()))
b = []
b.append(a[0])
i = 0
for i in range(1,n):    #消除相邻重复的数
    if a[i-1] != a[i]:
        b.append((a[i]))
x = max(b) #用x来存储列表b中的最大的数
c = [ 0 for i in range(10001)] # c 的索引就表示 水位下降到这个索引时 非零段(山峰)是增加1 还是减少了1

b.insert(0,0) #在第一个索引之前加入一个0  方便去比较
b.append(0) #在最后加入0

for i in range(1,len(b)-1):
    if b[i-1] < b[i] and b[i] > b[i+1]: #若比相邻的俩个数都大,就说明下降到这个水位后 非零段增加1
        c[b[i]] += 1
    elif b[i-1] > b[i] and b[i] <b[i+1]: # 若小就会把旁边的俩个非零段连接起来,非零段减少1
        c[b[i]] -= 1
max = 0
sum = 0 # 后缀和
for i in range(x,-1,-1): #因为水位是从最高的开始下降,所以需要后缀和,来判断下降到某一个水位时是增加还是减少。
    sum += c[i]#前缀和表示岛屿数
    if max < sum: #用max来记录最大的非零段
        max = sum
print(max)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值