代码拉取完成,页面将自动刷新
# -*- coding: utf-8 -*-
# @project : 《Atcoder》
# @Author : created by bensonrachel on 2021/8/26
# @File : TPM(step2)F - Segments with Small Spread(CF)(st表).py
# 使用ST表的做法
def create_log_table():
table = [0]*(n+1)
table[1]=0
for i in range(2,n+1):
table[i] = table[i//2]+1
return table
"""
打表,2的j次方<=区间长度len的最大的j,用递推式DP的思想打表记录所有的j
"""
def create_two_st():
for i in range(n):
st_max[i][0]=rate[i]#初始化,j=0,说明区间长度只有一个2**0=1,那就只有一个,所以为rate[i]
st_min[i][0]=rate[i]
for j in range(1,Log_table[n]+1):#j是阶段,外循环
i = 0
while(i+2**j-1<=n-1):#i加长度不能超出总长度的范围,所以st表有很大一部分是不会扫描到的。
st_max[i][j] = max(st_max[i][j-1],st_max[i+2**(j-1)][j-1])#取区间分开两半的最大值等于这个区间的最大值,这里是没有重合的部分的
st_min[i][j] = min(st_min[i][j-1],st_min[i+2**(j-1)][j-1])
i +=1
"""
建立ST表,这里因为要求一个最大值和一个最小值,所以会有两个st表,
"""
def query(l,r):
length = r-l+1
x = Log_table[length]#此区间长度对应Log表的j值。
return max(st_max[l][x],st_max[r-2**x+1][x])-min(st_min[l][x],st_min[r-2**x+1][x])#可以发现我们能使用至多两个预处理过的区间来覆盖询问区间
#这里是肯定会有覆盖重合的部分的,但是不影响最值,
"""
O(1)的查询操作:
对于每一个区间长度,可以瞬间找到它的区间最值
就是对此区间的起点往后划一段,从终点往前划一段,这两段长度是相等的,且一定有重合的部分,但是可以完全覆盖了这个区间。
"""
def TPM():
l = 0
res = 0
for r in range(n):
while(l <= r and query(l,r)>k):#while(query(l,r)>k):这样也可以ac
l += 1
res += (r-l+1)
return res
"""
st表做法,时间复杂度级别(nlogn)
静态(原数组的值不会修改)区间最值,区间GCD因为有重复性,所以可以用ST表的方法做
"""
if __name__ == "__main__":
n,k = map(int,input().split())
rate = [int(i) for i in input().split()]
Log_table = create_log_table()
st_max = [[0]*(18) for i in range(n)]
st_min = [[10**18+1]*(18) for i in range(n)]
"""
两个st表的定义,st_max[i][j]表示以i为起点,区间长度为2**j的最大值是多少。
st_min同理
"""
create_two_st()
ans = TPM()
print(ans)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。