蓝桥杯之算法模板题 Python版

Posted 风信子的猫Redamancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯之算法模板题 Python版相关的知识,希望对你有一定的参考价值。

蓝桥杯之算法模板题 Python版

文章目录


记录一下算法模板题,这样方便查阅和学习,希望好好加油

线段树

import os
import sys

N,Q = map(int,input().split())
arr = [0]
arr.extend(list(map(int,input().split())))
def ls(p):return p<<1 # p//2
def rs(p):return p<<1|1 # p//2 + 1
tree = [0 for _ in range(N<<2)] # 一共有2n个节点
tag = [0 for _ in range(N<<2)] # lazy_tag标记

def pushdown(p,pl,pr):
  if tag[p]!=0:
    mid = pl + pr >> 1
    addtag(ls(p),pl,mid,tag[p])
    addtag(rs(p),mid+1,pr,tag[p])
    tag[p] = 0
    # tree[p] = tree[lr(p)] + tree[rs(p)]
    
def push_up(p):
  tree[p] = tree[ls(p)] + tree[rs(p)]
# 搭建线段树 节点的值是求和
def bulid(p,pl,pr):
  if pl == pr:
    # tree[p] = float('-inf')
    tree[p] = arr[pl]
    return 
  mid = pl + pr>>1
  bulid(ls(p),pl,mid)
  bulid(rs(p),mid+1,pr)
  # tree[p] = tree[pl] + tree[pr]
  push_up(p)

# 增加lazy_tag标记
def addtag(p,pl,pr,d):
  tag[p] += d
  tree[p] += d*(pr-pl+1)

def query(p,pl,pr,L,R): # L,R是查询区间
  # 当前节点在查询区间内
  if L <= pl and pr <= R: return tree[p]
  pushdown(p,pl,pr) # 标记向下传递
  res = 0
  mid = pl + pr >>1
  if L <= mid:
    res+=query(ls(p),pl,mid,L,R) 
  if R > mid:
    res+=query(rs(p),mid+1,pr,L,R)
  return res

# 更新线段树,也就是加上k L,R是更新区间
def update(p,pl,pr,L,R,d):
  if L<=pl and pr<=R:
    addtag(p,pl,pr,d)
    return
  pushdown(p,pl,pr) # 标记向下传递
  mid = pl + pr >> 1
  if L <= mid: update(ls(p),pl,mid,L,R,d)
  if R > mid: update(rs(p),mid+1,pr,L,R,d)
  push_up(p)

bulid(1,1,N)
for _ in range(Q):
  q = list(map(int,input().split()))
  if q[0] == 1:
    update(1,1,N,q[1],q[2],q[3])
  elif q[0] == 2:
    print(query(1,1,N,q[1],q[2]))

import os
import sys
def ls(p):return p<<1
def rs(p):return p<<1|1
def push_up(p):tree[p]=tree[rs(p)]+tree[ls(p)]
def build(p,pl,pr):
  if pl==pr:
    tree[p]=1
    return
  mid=(pl+pr)>>1
  build(ls(p),pl,mid)
  build(rs(p),mid+1,pr)
  push_up(p)
def addtag(p,pl,pr,d):
  tag[p]=d
  tree[p]=d*(pr-pl+1)
def push_down(p,pl,pr):
  if ~tag[p]!=0:
    mid=(pl+pr)>>1
    addtag(ls(p),pl,mid,tag[p])
    addtag(rs(p),mid+1,pr,tag[p])
    tag[p]=-1
# 把1变成0
def update0(p,pl,pr,cnt):
  if cnt==0:return
  if tree[p]==cnt:
    addtag(p,pl,pr,0)
    return
  mid=(pl+pr)>>1
  push_down(p,pl,pr)
  if tree[ls(p)]>cnt:update0(ls(p),pl,mid,cnt)
  else:
    cnt-=tree[ls(p)]
    addtag(ls(p),pl,mid,0)
    update0(rs(p),mid+1,pr,cnt)
  push_up(p)
# 把0变成1
def update1(p,pl,pr,cnt):
  if cnt==0:return
  if pr-pl+1-tree[p]==cnt:
    addtag(p,pl,pr,1)
    return
  mid=(pl+pr)>>1
  push_down(p,pl,pr)
  if mid-pl+1-tree[ls(p)]>cnt:update1(ls(p),pl,mid,cnt)
  else:
    cnt-=(mid-pl+1-tree[ls(p)])
    addtag(ls(p),pl,mid,1)
    update1(rs(p),mid+1,pr,cnt)
  push_up(p)
def query(p,pl,pr,L,R):
  if L<=pl and pr<=R:return tree[p]
  push_down(p,pl,pr)
  mid=(pl+pr)>>1
  res=0
  if L<=mid:res+=query(ls(p),pl,mid,L,R)
  if R>mid:res+=query(rs(p),mid+1,pr,L,R)
  return res
n,m=map(int,input().split())
tree=[0 for _ in range(n<<2)]
tag=[-1 for _ in range(n<<2)]
build(1,1,n)
for _ in range(m):
  op,num=map(int,input().split())
  if op==0:
    pos=n-tree[1]
    cnt=max(0,num-pos)
    update0(1,1,n,cnt)
  elif op==1:
    pos=tree[1]
    cnt=max(0,n-num+1-pos)
    update1(1,1,n,cnt)
ans1,ans2=[],[]
for i in range(1,n+1):
  if query(1,1,n,i,i)==0:ans1.append(i)
  else:ans2.append(i)
for x in ans1[::-1]+ans2:
  print(x,end=' ')

DP 动态规划

dp, LIS **

'''
https://www.lanqiao.cn/problems/1188/learning/
难度: 中等   标签: dp, LIS
'''

import os
import sys
import bisect
# 请在此输入您的代码

n = int(input())
a = list(map(int,input().split()))

dp = [float('inf')]*(n+1)
dp[0] = a[0]
for i in range(1,n):
    t = bisect.bisect_left(dp,a[i])
    dp[t] = a[i]

print(bisect.bisect_left(dp,float('inf')))

01背包

动态转移方程
f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i − 1 ] [ j − v ] + w ) ( j > v ) f[i][j] = max(f[i-1][j], f[i-1][j-v] + w)(j>v) f[i][j]=max(f[i1][j],f[i1][jv]+w)(j>v)

# https://www.lanqiao.cn/problems/1174/learning/
# 难度: 简单   标签: dp, 背包, 01背包
import os
import sys


# 请在此输入您的代码
N,V = map(int,input().split())
# f[N][V]
# f[i][j] 代表 i 件物品 , 容量为 j 的时候,得到最大的价值
f = [[0]*(V+1) for _ in range(N+1)]

for i in range(1,N+1):
    # v为体积, w为价值
    v, w = map(int, input().split())
    for j in range(1,V+1):
        # 第i件物品有两种选择,
        # 第1种是选第i件物品,f[i-1][j]
        # 第2种是不选第i件物品,f[i-1][j]
        if j < v: 
            f[i][j] = f[i-1][j]
        else:
            f[i][j] = max(f[i-1][j], f[i-1][j-v] + w)

print(f[N][V])

完全背包

一般就是
f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j − k ∗ v ] + w ∗ k ) ( 0 < = k < j / / v ) f[i][j] = max(f[i-1][j-k*v] + w*k)(0<=k<j//v) f[i][j]=max(f[i1][jkv]+wk)(0<=k<j//v)
不过可以转化为动态转移方程
f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i ] [ j − v ] + w ) f[i][j] = max(f[i-1][j],f[i][j-v] + w) f[i][j]=max(f[i1][j],f[i][jv]+w)

'''
https://www.lanqiao.cn/problems/1175/learning/
难度: 简单   标签: DP, 背包, 完全背包
'''

import os
import sys

# 请在此输入您的代码
N,V = map(int,input().split())

# f[i][j]表示前i种,总体积不超过j,最大的总价值
f = [[0]*(V+1) for _ in range(N+1)]


# 完全背包问题,可以买多个
for i in range(1,N+1):
    v,w = map(int,input().split以上是关于蓝桥杯之算法模板题 Python版的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯之数论专题

蓝桥杯之FJ的字符串

蓝桥杯之K好数问题

蓝桥杯之16进制转8进制

[蓝桥杯Python]算法练习算法基础算法训练算法模板(持续更新)

BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版