1 Star 1 Fork 0

bensonrachel/Atcoder_algorithm

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
TPM(step2)F - Segments with Small Spread(CF)(st表).py 2.55 KB
一键复制 编辑 原始数据 按行查看 历史
# -*- 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)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/bensonrachel/atcoder_algorithm.git
git@gitee.com:bensonrachel/atcoder_algorithm.git
bensonrachel
atcoder_algorithm
Atcoder_algorithm
master

搜索帮助