上周周赛不会写 st 表结果坐牢了,于是痛定思痛,整理了一些模板。随着以后学习,可能会更新(比如线段树。。。)
update:
class BIT:
def __init__(self, A):
self.tree = [0]*(len(A)+1)
self.A = [0]*len(A)
for i,a in enumerate(A):
self.update(i,a)
def update(self, i, x):
add = x - self.A[i]
self.A[i] = x
i += 1
while i < len(self.tree):
self.tree[i] += add
i += i & (-i)
def get(self, i):
res, i = 0, i+1
while i > 0:
res += self.tree[i]
i &= i-1
return res
def query(self,l,r):
return self.get(r)-self.get(l-1)典型题目:
class BIT:
def __init__(self, A):
self.tree = [0]*(len(A)+1)
self.A = [0]*len(A)
for i,a in enumerate(A):
self.update(i,a)
def update(self, i, x):
add = x - self.A[i]
self.A[i] = x
i += 1
while i < len(self.tree):
self.tree[i] += add
i += i & (-i)
def get(self, i):
res, i = 0, i+1
while i > 0:
res += self.tree[i]
i &= i-1
return res
def query(self,l,r):
return self.get(r)-self.get(l-1)
class NumArray:
def __init__(self, nums: List[int]):
self.tree = BIT(nums)
def update(self, index: int, val: int) -> None:
self.tree.update(index,val)
def sumRange(self, left: int, right: int) -> int:
return self.tree.query(left,right)def kmp(s):
nxt, j = [-1], -1
for i in range(len(s)):
while j >= 0 and s[i] != s[j]:
j = nxt[j]
j += 1
nxt.append(j)
return nxt # nxt[i]:i-1结尾的最大真前缀长度典型题目:
def kmp(s):
nxt, j = [-1], -1
for i in range(len(s)):
while j >= 0 and s[i] != s[j]:
j = nxt[j]
j += 1
nxt.append(j)
return nxt
class Solution:
def longestPrefix(self, s: str) -> str:
i = kmp(s)[-1]
return s[:i]def manacher(s):
n = len(s)
A, B = [], [1]*n
mid, r = 0, 0
for i in range(n):
a = min(A[2*mid-i], r-i) if r>i else 0
while i-a and i+a<n-1 and s[i-a-1]==s[i+a+1]:
a += 1
B[i+a] = max(B[i+a],a*2+1)
A.append(a)
if i+a>r:
mid, r = i, i+a
return B # B[i]:i结尾的最大回文子串长度(奇数)
ss = '#' + '#'.join(s) + '#'
B = [(b+1)//2 for b in manacher(ss)[1::2]] # B[i]:i结尾的最大回文子串长度(所有)典型题目:
class Solution:
def shortestPalindrome(self, s: str) -> str:
def manacher(s):
n = len(s)
A, B = [], [1]*n
mid, r = 0, 0
for i in range(n):
a = min(A[2*mid-i], r-i) if r>i else 0
while i-a and i+a<n-1 and s[i-a-1]==s[i+a+1]:
a += 1
B[i+a] = max(B[i+a],a*2+1)
A.append(a)
if i+a>r:
mid, r = i, i+a
return B
ss = '#' + '#'.join(s) + '#'
B = [(b+1)//2 for b in manacher(ss)[1::2]]
for i in range(len(B)-1,-1,-1):
if B[i]==i+1:
return s[i+1:][::-1]+sdef zfunc(s):
n = len(s)
z, l, r = [0]*n, 0, 0
for i in range(1,n):
z[i] = max(min(z[i-l],r-i+1), 0)
while i+z[i]<n and s[z[i]]==s[i+z[i]]:
l, r = i, i+z[i]
z[i] += 1
return z # z[i]:lcp(后缀i,后缀0) 典型题目:
ma =
def get_primes(M):
f = [1]*M
for i in range(2,isqrt(M)+1):
if f[i]:
f[i*i:M:i] = [0] * ((M-1-i*i)//i+1)
return [i for i in range(2,M) if f[i]]
primes = get_primes(isqrt(ma)+1)
@cache
def factor(x):
ct = Counter()
for p in primes:
while x%p==0:
x//=p
ct[p] += 1
if x>1:
ct[x] += 1
return ct典型题目:
ma = 10**6
def get_primes(M):
f = [1]*M
for i in range(2,isqrt(M)+1):
if f[i]:
f[i*i:M:i] = [0] * ((M-1-i*i)//i+1)
return [i for i in range(2,M) if f[i]]
primes = get_primes(isqrt(ma)+1)
@cache
def factor(x):
ct = Counter()
for p in primes:
while x%p==0:
x//=p
ct[p] += 1
if x>1:
ct[x] += 1
return ct
class Solution:
def findValidSplit(self, nums: List[int]) -> int:
n = len(nums)
d = {p:i for i in range(n) for p in factor(nums[i])}
r = 0
for i in range(n-1):
for p in factor(nums[i]):
r = max(r,d[p])
if r==i:
return i
return -1ma =
mod = 10**9+7
fac, inv = [1]*(ma+1), [1]*(ma+1)
for i in range(1,ma+1):
fac[i] = fac[i-1]*i%mod
inv[i] = pow(fac[i],-1,mod)典型题目:
ma = 1000
mod = 10**9+7
fac, inv = [1]*(ma+1), [1]*(ma+1)
for i in range(1,ma+1):
fac[i] = fac[i-1]*i%mod
inv[i] = pow(fac[i],-1,mod)
class Solution:
def numOfWays(self, nums: List[int]) -> int:
def dfs(nums):
if not nums:
return 1
A = [[],[]]
for x in nums[1:]:
A[x>nums[0]].append(x)
a, b = len(A[0]), len(A[1])
return fac[a+b]*inv[a]*inv[b]*dfs(A[0])*dfs(A[1])%mod
return dfs(nums)-1