1. 在学习这个课程的同时,每三天复习一下算法基础课(重做一下习题),将基础课的知识用思维导图归纳下。
2. 2022.2.12 - 2022.2.24:花两周时间把Python的两套蓝桥杯真题写了
3. 蓝桥杯学完和基础课复习完就刷acwing上的蓝桥杯题(用IDLE编译器coding),这样子一共做过的题目数量应该在300道左右。
Day 1 (2021.12.25)
递归的执行顺序:
2^20 = 10^6
2^63 = 10^8
# acwing 92. 递归实现指数型枚举
# 代码 1,使用append和pop操作
def dfs(u):
if u==n+1:
print(' '.join(map(str,a)))
return
a.append(u)
dfs(u+1)
a.pop()
dfs(u+1)
if __name__ == '__main__':
a = []
n = int(input())
dfs(1)
# 代码 2,使用修改操作
N = 16
def dfs(u):
if u==n+1:
for i in range(1,N):
if a[i]==1: print(i, end=' ')
print()
return
a[u]=1
dfs(u+1)
a[u]=0
dfs(u+1)
if __name__ == '__main__':
a = [0]*N
n = int(input())
dfs(1)
实验后发现对列表赋值这个操作是非常耗时间的
Day 2 (2021.12.26)
# acwing 94. 递归实现排列型枚举
N = 10
def dfs(u):
if u>n:
print(' '.join(map(str, a)))
return
for i in range(1,n+1):
if not st[i]:
st[i] = True
a.append(i)
dfs(u+1)
a.pop()
st[i] = False
return
if __name__ == '__main__':
st, a = [False]*N, []
n = int(input())
dfs(1)
# acwing 93. 递归实现组合型枚举
N = 30
def dfs(u):
if u>m:
print(' '.join(map(str, a)))
return 0
for i in range(1,n+1):
if not st[i]:
if len(a) and a[-1]>i:
continue
st[i] = True
a.append(i)
dfs(u+1)
st[i] = False
a.pop()
return 0
if __name__ == '__main__':
n, m = map(int, input().split())
a, st = [], [False]*N
dfs(1)
# yxc 思路
# -----------------------------------------------------------
N = 30
def dfs(u, start):
# 剪枝
if len(a)+n-start+1 < m: return
if u>m:
print(' '.join(map(str, a)))
return
for i in range(start, n+1):
a.append(i)
dfs(u+1,i+1)
a.pop()
if __name__ == '__main__':
a = []
n, m = map(int, input().split())
dfs(1,1)
# acwing. 1209. 带分数
def count(u, inv_u):
global res
u, idx = str(u), 1
while True:
numerator, denominator, idx = str(idx*inv_u), str(idx), idx+1
if len(numerator) + len(denominator) > 9-len(u): break
s = set(list(numerator+denominator+u))
if '0' in s: continue
for i in range(1,10):
if str(i) not in s: break
if i==9: res+=1
if __name__ == '__main__':
n, res = int(input()), 0
for i in range(1,n):
count(i,n-i)
print(res)
# Acwing 1209. 带分数
# yxc 的思路一,直接全排列的方法超时
N = 10
def count(l,r):
res = 0
for i in range(l,r+1):
res = res*10+a[i]
return res
def check():
global res
for i in range(1,8):
if count(1, i) > n: break
for j in range(i+1,9):
if (n - count(1,i)) * count(i+1,j) == count(j+1,9):
res += 1
def dfs(u):
if u>9:
check()
return
for i in range(1,10):
if not st[i]:
a.append(i)
st[i] = True
dfs(u+1)
st[i] = False
a.pop()
return
if __name__ == '__main__':
n = int(input())
a, st = [0], [False]*N
res = 0
dfs(1)
print(res)
# yxc 的思路 2
N = 10
def check(tmp_a, tmp_c):
global res
tmp_b = (n - tmp_a) * tmp_c
tmp_str = list(str(tmp_b) + str(tmp_c) + str(tmp_a))
if len(tmp_str) != 9: return False
for i in range(1, 10):
if str(i) not in tmp_str: return False
return True
def dfs_c(u, tmp_a, tmp_c):
global res
if u>9: return
if check(tmp_a, tmp_c): res += 1
for i in range(1,10):
if not st[i]:
st[i] = True
dfs_c(u+1, tmp_a, tmp_c*10+i)
st[i] = False
def dfs_a(u, tmp_a):
if tmp_a>=n: return
if tmp_a: dfs_c(u, tmp_a, 0)
for i in range(1,10):
if not st[i]:
st[i] = True
dfs_a(u+1, tmp_a*10+i)
st[i] = False
return
if __name__ == '__main__':
n = int(input())
st = [False]*N
res = 0
dfs_a(0, 0)
print(res)
Day 3 (2021.12.27)
# acwing 717. 简单斐波那契
if __name__ == '__main__':
a, b = 0, 1
n = int(input())
for _ in range(n):
print(a, end=' ')
b, a = a+b, b
Day 4 (2021.12.28)
递归是把子问题分解成同类子问题,递推先把子问题做完,再用子问题把原问题解出来
# acwing 95. 费解的开关
import copy
directions = [(1,0),(0,1),(0,-1),(-1,0),(0,0)]
def turn(x,y,cur_w):
for direction in directions:
a, b = x + direction[0], y + direction[1]
if a>=0 and a<5 and b>=0 and b<5: cur_w[a][b] ^= 1
def light():
res = 0x3f3f3f3f
for op in range(1<<5):
copy_w, step = copy.deepcopy(w), 0
for i in range(5):
if (op>>i)&1:
step += 1
turn(0,i,copy_w)
for i in range(4):
for j in range(5):
if copy_w[i][j]==0:
step += 1
turn(i+1,j,copy_w)
flag = True
for i in range(5):
if copy_w[4][i]==0:
flag = False
break
if flag: res = min(res, step)
return res if res<=6 else -1
if __name__ == '__main__':
n = int(input())
for i in range(n):
w = []
for j in range(5):
w.append([int(x) for x in list(input())])
if i!=n-1: input()
print(light())
Day 5 (2021.12.30)
# acwing 116. 飞行员兄弟
import copy
def turn(x,y,cur_w):
for i in range(4):
if cur_w[x][i] == '+': cur_w[x][i] = '-'
else: cur_w[x][i] = '+'
if cur_w[i][y] == '+': cur_w[i][y] = '-'
else: cur_w[i][y] = '+'
if cur_w[x][y] == '+': cur_w[x][y] = '-'
else: cur_w[x][y] = '+'
def findWay():
ways, res = [], 0x3f3f3f3f
for op in range(1,1<<16):
copy_w, step, temp_ways = copy.deepcopy(w), 0, []
for i in range(16):
if (op>>i)&1:
step += 1
temp_ways.append((i//4+1,i%4+1))
turn(i//4,i%4,copy_w)
flag = True
for i in range(16):
if copy_w[i//4][i%4] == '+':
flag = False
break
if flag and res>step:
res, ways = step, temp_ways
return res, ways
if __name__ == '__main__':
w = []
for _ in range(4):
w.append(list(input()))
times, ans = findWay()
print(times)
for item in ans:
print(item[0], item[1])
Day 6 (2022.1.2)
# 自己的思路是,一定会有偶数个不同
# 则要使这偶数个不同变成相同,需要两两一组,如:0,2 6,13 14,15
# 操作步数则是2-0 + 13-6 + 15-14
# acwing 1208. 翻硬币
if __name__ == '__main__':
a, b = list(input()), list(input())
st = [1 if a[i]==b[i] else 0 for i in range(len(a))]
res, z_list = 0, []
for i in range(len(a)):
if not st[i]:
z_list.append(i)
for i in range(0,len(z_list),2):
res += z_list[i+1] - z_list[i]
print(res)
# acwing 1208. 翻硬币
if __name__ == '__main__':
a, b = list(input()), list(input())
step = 0
for i in range(len(a)-1):
if a[i]!=b[i]:
step += 1
if a[i]=='*': a[i]='o'
else: a[i]='*'
if a[i+1] == '*': a[i+1] = 'o'
else: a[i+1] = '*'
print(step)
Day 7 (2022.1.3)
今天复习了八数码这道题,然后写了下面这个代码,发现过不了,最后研究发现应该是deepcopy很耗时间。
from collections import deque
from copy import deepcopy
from collections import defaultdict
directions = [(1,0),(0,1),(-1,0),(0,-1)]
def bfs():
tried, q = defaultdict(int), deque()
q.append((w,0))
while q:
now_state, step = q.popleft()
x, y = now_state.index('x')//3, now_state.index('x')%3
for direction in directions:
now_state_copy = deepcopy(now_state)
x_op, y_op = x+direction[0], y+direction[1]
if x_op>=0 and x_op<3 and y_op>=0 and y_op<3:
now_state_copy[x_op*3+y_op], now_state_copy[x*3+y] = now_state_copy[x*3+y], now_state_copy[x_op*3+y_op]
if not tried[str(now_state_copy)]:
tried[str(now_state_copy)] = step+1
q.append((now_state_copy, step+1))
if now_state_copy==right:
print(step+1)
return
print(-1)
return
if __name__ == '__main__':
w, right = list(input().split()), list('12345678x')
bfs()
Day 8 (2022.1.4)
二分基础课学过,这里就复习下题。
两个点:1.左边界是找所有>=x的数 2.if 判断 l 的时候求mid要+1除以2(简称let it go)
# acwing 789. 数的范围
if __name__ == '__main__':
n, q = map(int, input().split())
a = [int(x) for x in input().split()]
for _ in range(q):
k = int(input())
l, r = 0, len(a) - 1
while l < r:
mid = (l + r) // 2
if a[mid] >= k:
r = mid
else:
l = mid + 1
if a[l]!=k:
print('-1 -1')
continue
else: print(l, end=' ')
l, r = 0, len(a) - 1
while l < r:
mid = (l + r + 1) // 2
if a[mid] <= k:
l = mid
else:
r = mid - 1
print(l)
Day 9 (2022.1.5)
# acwing 790. 数的三次方根
eps = 1e-8
if __name__ == '__main__':
n = float(input())
l, r = -100, 100
while True:
mid = (l+r)/2
if abs(abs(mid**3)-abs(n)) < eps:
print("{:.6f}".format(mid))
exit(0)
elif mid**3<n: l=mid
else: r=mid
# acwing 730. 机器人跳跃问题
# yxl 的思路是可以优化提前退出for循环,只要当前mid>1e5
# 版本 1,还是推荐版本 2哈,跟着模板走
if __name__ == '__main__':
n = int(input())
a = [int(x) for x in input().split()]
l, r = min(a), max(a)
while l<r:
mid = (l+r)//2
flag = True
for i in range(n):
if a[i]>mid:
mid = mid - (a[i]-mid)
if mid<0:
l = (l+r)//2+1
flag = False
break
else: mid = mid + (mid-a[i])
if flag: r = (l+r)//2
print(l)
# 版本 2
# acwing 730. 机器人跳跃问题
def check(k):
for i in range(n):
k = 2*k - a[i]
if k<0: return False
return True
if __name__ == '__main__':
n = int(input())
a = [int(x) for x in input().split()]
l, r = 0, max(a)
while l<r:
mid = (l+r)//2
if check(mid): r=mid
else: l=mid+1
print(l)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int h[N];
bool check(int e)
{
for (int i = 1; i <= n; i ++ )
{
e = e * 2 - h[i];
if (e >= 1e5) return true;
if (e < 0) return false;
}
return true;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
int l = 0, r = 1e5;
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}
Day 10 (2022.1.6)
# acwing 1221. 四平方和
# Python 3 通过版,太多判断浪费时间。
import math
if __name__ == '__main__':
n = int(input())
s, root = {}, int(math.sqrt(n)+2)
for c in range(root):
for d in range(c,root):
t = c*c + d*d
if t not in s: s[t] = (c,d)
for a in range(root):
for b in range(a,root):
t = n - a*a - b*b
if t in s:
print(a,b,s[t][0],s[t][1])
exit()
# acwing 1221. 四平方和
from collections import defaultdict
if __name__ == '__main__':
n = int(input())
s = defaultdict(int)
for c in range(n+1):
if c*c<=n:
for d in range(c,n+1):
t = c*c + d*d
if t<=n:
# 可以替换成 if t not in s 这个操作
# 或者s.get(t,-1)
if not s[t]: s[t] = (c,d)
else: break
else: break
for a in range(n+1):
if a*a<=n:
for b in range(a,n+1):
t = n - a*a - b*b
if s[t]:
print(a,b,s[t][0],s[t][1])
exit()
# acwing 1221. 四平方和
if __name__ == '__main__':
n = int(input())
s = []
for c in range(n+1):
if c*c<=n:
for d in range(c,n+1):
t = c*c + d*d
if t<=n:
s.append((t,c,d))
else: break
else: break
s.sort()
for a in range(n+1):
if a*a<=n:
for b in range(a,n+1):
t = n - a*a - b*b
l, r = 0, len(s)-1
while l<r:
mid = (l+r)//2
if s[mid][0]>=t:r=mid
else:l=mid+1
if s[l][0]==t:
print(a,b,s[l][1],s[l][2])
exit()
# acwing 1227. 分巧克力
def check(edge):
res = 0
for square in a:
x, y = square
res += (x//edge)*(y//edge)
if res>=k: return True
else: return False
if __name__ == '__main__':
n, k= map(int,input().split())
a, v_max = [], 0
for _ in range(n):
x, y = map(int,input().split())
v_max = max(v_max,x,y)
a.append((x,y))
l, r = 1, v_max
while l<r:
mid = (l+r+1)//2
if check(mid): l=mid
else: r=mid-1
print(l)
Day 11 (2022.1.7)
# acwing 99. 激光炸弹
# 这道题目描述一点都不准确!
N = 5002
if __name__ == '__main__':
n, r = map(int, input().split())
target, r = [[0]*N for _ in range(N)], min(5001,r)
row, col = r, r
for _ in range(n):
x,y,w = map(int, input().split())
target[x+1][y+1] += w
row, col = max(row,x+1), max(col,y+1)
res = 0
for i in range(1,row+1):
for j in range(1,col+1):
target[i][j] += - target[i-1][j-1] + target[i-1][j] + target[i][j-1]
if i>=r and j>=r: res = max(res, target[i][j] + target[i-r][j-r] - target[i][j-r] - target[i-r][j])
print(res)
Day 12 (2022.1.8)
今天发现了一个问题,为什么同样的代码和数据,在本机上运行特别慢,差了几十几百倍的速度,就是acwing 99题,上面的代码和下面这个数据。
2 1000000000
0 0 1
1 1 1
# acwing 1230. K倍区间
# cnt[0] 是指的它自己本身就是一个满足条件的解
N = 100010
if __name__ == '__main__':
n, k = map(int, input().split())
sum, cnt = [0]*N, [0]*N
res = 0
for i in range(1,n+1):
sum[i] = int(input())
sum[i] = (sum[i] + sum[i-1])%k
res += cnt[sum[i]]
cnt[sum[i]] += 1
print(res + cnt[0])
# acwing 1205. 买不到的数目
if __name__ == '__main__':
n, m = map(int,input().split())
print((n-1)*(m-1)-1)
# acwing 1211. 蚂蚁感冒
if __name__ == '__main__':
n = int(input())
a = [int(x) for x in input().split()]
# 分别表示左边向右走的蚂蚁数量,和右边向左走的蚂蚁数量
ltr, rtl = 0, 0
for i in range(1,n):
if abs(a[i]) < abs(a[0]) and a[i]>0: ltr += 1
elif abs(a[i]) > abs(a[0]) and a[i]<0: rtl += 1
if (a[0]>0 and rtl==0) or (a[0]<0 and ltr==0): print(1)
else: print(ltr+rtl+1)
# acwing 1216.饮料换购
if __name__ == '__main__':
n = int(input())
res = n
while n>=3:
res += n//3
n = n//3 + n%3
print(res)
Day 13 (2022.1.9)
今天复习了算法基础课 树形dp、记忆化搜索和蓝桥杯简单DP例题
Day 14 (2022.1.11)
# acwing 1212. 地宫取宝
# 集合划分就相当于是上一步的状态划分(把所有上一步转移到这一步的状态划分成不重不漏的几类)
N, MOD = 54, 1000000007
if __name__ == '__main__':
n, m, k = map(int, input().split())
f = [[[[0] * 14 for _ in range(13)] for _ in range(N)] for _ in range(N)]
w = [[0] * (m + 1)]
for i in range(1,n+1):
w.append([0] + [int(x)+1 for x in input().split()])
f[1][1][1][w[1][1]] = f[1][1][0][0] = 1
for i in range(1,n+1):
for j in range(1,m+1):
if i==j==1: continue
for cnt in range(k+1):
for t in range(14):
f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i-1][j][cnt][t]) % MOD
f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i][j-1][cnt][t]) % MOD
if cnt>0 and w[i][j] == t:
for v in range(t):
f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i - 1][j][cnt-1][v]) % MOD
f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i][j - 1][cnt-1][v]) % MOD
res = 0
for i in range(14): res = (f[n][m][k][i] + res) % MOD
print(res)
Day 15 (2022.1.13)
# acwing 1214. 波动数列
N, M = 1010, 100000007
if __name__ == '__main__':
n,s,a,b = map(int, input().split())
f = [[0]*N for _ in range(N)]
f[0][0] = 1
for i in range(1,n):
for j in range(n):
f[i][j] = (f[i-1][(j-(n-i)*a)%n] + f[i-1][(j+(n-i)*b)%n])%M
print(f[n-1][s%n])
Day 16 (2022.1.16)
# acwing 1236. 递增三元组
# cnt_aa 小于等于1,2,3的数分别有多少
# 注意要给每个数+1
N = 100010
if __name__ == '__main__':
n = int(input())
A, B, C = [int(x)+1 for x in input().split()], \
[int(x)+1 for x in input().split()], [int(x)+1 for x in input().split()]
cnt_a, cnt_c, cnt_aa, cnt_cc = [0]*N, [0]*N, [0]*N, [0]*N
for i in range(n): cnt_a[A[i]] += 1
for i in range(1,N): cnt_aa[i] = cnt_aa[i-1] + cnt_a[i]
for i in range(n): cnt_c[C[i]] += 1
for i in range(1,N): cnt_cc[i] = cnt_cc[i-1] + cnt_c[i]
res = 0
for i in range(n):
res += cnt_aa[B[i]-1] * (cnt_cc[N-1] - cnt_cc[B[i]])
print(res)
# acwing 1236. 递增三元组
N = 100010
if __name__ == '__main__':
n = int(input())
a,b,c = [int(x)+1 for x in input().split()],\
[int(x)+1 for x in input().split()], [int(x)+1 for x in input().split()]
lb,gb,cnt_a,cnt_c,cnt_c_c,cnt_a_a = [0]*N, [0]*N,[0]*N,[0]*N,[0]*N,[0]*N
for i in range(n): cnt_a[a[i]]+=1
for i in range(1,N): cnt_a_a[i] = cnt_a_a[i-1] + cnt_a[i]
for i in range(n): lb[i] = cnt_a_a[b[i]-1]
for i in range(n): cnt_c[c[i]]+=1
for i in range(1,N): cnt_c_c[i] += cnt_c_c[i-1] + cnt_c[i]
for i in range(n): gb[i] = cnt_c_c[N-1] - cnt_c_c[b[i]]
res = 0
for i in range(n): res += lb[i]*gb[i]
print(res)
# Python的-1回取到最后一个值去,所以也可以不+1
N, L = 100010, 100001
if __name__ == '__main__':
n = int(input())
a,b,c = [int(x) for x in input().split()],\
[int(x) for x in input().split()], [int(x) for x in input().split()]
lb,gb,cnt_a,cnt_c,cnt_c_c,cnt_a_a = [0]*N, [0]*N,[0]*N,[0]*N,[0]*N,[0]*N
for i in range(n): cnt_a[a[i]]+=1
for i in range(L+1): cnt_a_a[i] = cnt_a_a[i-1] + cnt_a[i]
for i in range(n): lb[i] = cnt_a_a[b[i]-1]
for i in range(n): cnt_c[c[i]]+=1
for i in range(L+1): cnt_c_c[i] = cnt_c_c[i-1] + cnt_c[i]
for i in range(n): gb[i] = cnt_c_c[L] - cnt_c_c[b[i]]
res = 0
for i in range(n): res += lb[i]*gb[i]
print(res)
# acwing 1236. 递增三元组
# 二分算法得注意分情况讨论 >=<
N = 100010
def binary_search_great(arr, x):
l, r = 0, n-1
while l<r:
mid = (l+r)//2
if arr[mid]>=x: r=mid
else: l=mid+1
if arr[l]>=x: return l
else: return n
def binary_search_less(arr, x):
l, r = 0, n - 1
while l < r:
mid = (l + r + 1) // 2
if arr[mid] <= x: l = mid
else: r = mid - 1
if arr[l]<=x: return n-1-l
else: return n
if __name__ == '__main__':
n = int(input())
A, B, C = [int(x) for x in input().split()], \
[int(x) for x in input().split()], [int(x) for x in input().split()]
A.sort()
C.sort()
res = 0
for i in range(n):
res += binary_search_great(A, B[i]) * binary_search_less(C, B[i])
print(res)
Day 17 (2022.1.17)
# acwing. 1245. 特别数的和
if __name__ == '__main__':
n = int(input())
res = 0
for i in range(1,n+1):
n_str = str(i)
if n_str.find('2')!=-1 or n_str.find('0')!=-1 or n_str.find('1')!=-1 or n_str.find('9')!=-1:
res += i
print(res)
# acwing 1204. 错误票据
N = 100010
if __name__ == '__main__':
n = int(input())
a, st, repeat, interval = [], [0]*N, 0, 0
for _ in range(n):
a.extend([int(x) for x in input().split()])
for i in range(len(a)):
if st[a[i]]: repeat=a[i]
else: st[a[i]] = True
for i in range(min(a),N):
if not st[i]:
interval=i
break
print(interval,repeat)
Day 18 (2022.1.18)
# acwing 466. 回文日期
# 直接枚举每一天
Month = [0,31,28,31,30,31,30,31,31,30,31,30,31]
def isValidDate(date):
year, month, day = date//10000, (date//100)%100, date%100
if month==0 or month>12: return False
if month==2:
if (year%4==0 and year%100) or year%400:
if day==0 or day>29: return False
else:
if day==0 or day>28: return False
else:
if day==0 or day>Month[month]: return False
return True
def isPalindrom(date):
if str(date)==str(date)[::-1]: return True
return False
if __name__ == '__main__':
start, end, res = int(input()), int(input()), 0
for i in range(start, end+1):
if isValidDate(i) and isPalindrom(i): res += 1
print(res)
# acwing 466. 回文日期
Month = [0,31,28,31,30,31,30,31,31,30,31,30,31]
def is_valid(date):
if date<start or date>end: return False
year, month, day = date//10000, (date%10000)//100, date%100
if month<1 or month>12: return False
if month==2:
if (year%4==0 and year%100) or (year%400==0):
if day<1 or day>29: return False
elif day<1 or day>28: return False
elif day<1 or day>Month[month]: return False
return True
if __name__ == '__main__':
start, end, a, res = int(input()), int(input()), [], 0
for i in range(1000,10000):
tmp_str = str(i) + str(i)[::-1]
a.append(int(tmp_str))
for item in a:
if is_valid(item): res+=1
print(res)
Day 19 (2022.1.19)
# acwing 787. 归并排序
def merge_sort(st, ed):
if st>=ed: return
mid = (st + ed)//2
merge_sort(st,mid)
merge_sort(mid+1,ed)
tmp_list, tmp_1, tmp_2 = [], st, mid+1
while tmp_1<=mid and tmp_2<=ed:
if a[tmp_1]<a[tmp_2]:
tmp_list.append(a[tmp_1])
tmp_1 += 1
else:
tmp_list.append(a[tmp_2])
tmp_2 += 1
tmp_list.extend(a[tmp_1:mid+1])
tmp_list.extend(a[tmp_2:ed+1])
a[st:ed+1] = tmp_list[:]
if __name__ == '__main__':
n = int(input())
a = [int(x) for x in input().split()]
merge_sort(0,n-1)
print(" ".join(map(str,a)))
Day 20 (2022.1.20)
# acwing 1219. 移动距离
import math
if __name__ == '__main__':
w, m, n = map(int,input().split())
m_row, n_row = math.ceil(m/w), math.ceil(n/w)
if math.ceil(m/w)%2:
if m%w: m_col = m%w
else: m_col = w
else:
if m%w: m_col = w + 1 - m%w
else: m_col = 1
if math.ceil(n/w)%2:
if n%w: n_col = n%w
else: n_col = w
else:
if n%w: n_col = w + 1 - n%w
else: n_col = 1
res = abs(n_col-m_col)+abs(n_row-m_row)
print(res)
# 将下标变成从0开始(0行,0列),则答案比上面的代码逻辑要简单的多
# 所有行号都是直接向下取整,列号都是取余。如果从1开始则要特判
# 这道题涉及到了一个知识点,就是二维变一维(
# 或者一维变二维的时候,一维下标最好从0开始)
# acwing 1219. 移动距离
if __name__ == '__main__':
w, m, n = map(int,input().split())
m, n = m-1, n-1
row_m, row_n, col_m, col_n = m//w, n//w, m%w, n%w
if row_m % 2: col_m = w - 1 - col_m
if row_n % 2: col_n = w - 1 - col_n
print(abs(row_m-row_n) + abs(col_m-col_n))
# acwing 1229. 日期问题
# YYMMDD, MMDDYY, DDMMYY
# 注意点:去除重复日期
MONTH = [0,31,28,31,30,31,30,31,31,30,31,30,31]
def isValidMonthAndDay(YY,MM,DD):
if YY>=60: YY = 1900+YY
else: YY = 2000+YY
if MM==0 or MM>12: return False
if MM==2:
if (YY%4==0 and YY%100) or YY%400==0:
if DD==0 or DD>29: return False
elif DD==0 or DD>28: return False
elif DD==0 or DD>MONTH[MM]: return False
return True
if __name__ == '__main__':
A,B,C = list(map(int,input().split('/')))
res = set()
if isValidMonthAndDay(A,B,C):
if A>=60: res.add(19000000+A*10000+B*100+C)
else: res.add(20000000+A*10000+B*100+C)
if isValidMonthAndDay(C,A,B):
if C>=60: res.add(19000000+C*10000+A*100+B)
else: res.add(20000000+C*10000+A*100+B)
if isValidMonthAndDay(C,B,A):
if C>=60: res.add(19000000+C*10000+B*100+A)
else: res.add(20000000+C*10000+B*100+A)
res = list(res)
res.sort()
for date in res:
date = str(date)
print(date[:4]+'-'+date[4:6]+'-'+date[6:])
Day 21 (2022.1.21)
# acwing 1231. 航班时间
# 这道题首先这个思维就没有想到,时差一加一减就没有了
# 然后转换成秒进行计算会大大降低复杂度也没想到
# 最后格式化输出补0也没有想到简单的方法。。。
# 同时,统一输入格式可以降低复杂度
def get_time(date):
start, end, days = date.split()
seconds1 = int(start[:2])*3600 + int(start[3:5])*60 + int(start[6:8])
seconds2 = int(end[:2])*3600 + int(end[3:5])*60 + int(end[6:8]) + int(days[2])*24*3600
return seconds2-seconds1
if __name__ == '__main__':
n = int(input())
for _ in range(n):
flight1, flight2 = input(), input()
if flight1[-1] != ')': flight1 += ' (+0)'
if flight2[-1] != ')': flight2 += ' (+0)'
ans = (get_time(flight1) + get_time(flight2))//2
print('{:0>2d}:{:0>2d}:{:0>2d}'.format(ans//3600,ans%3600//60,ans%60))
Day 22 (2022.1.22)
# acwing 1241. 外卖店优先级
# 直接用st[i]=True来表示是否在队列,可以减少判断是否在,然后pop的操作。
if __name__ == '__main__':
n, m, T = map(int, input().split())
score, last, st, orders = [0]*(n+1), [0]*(n+1), [0]*(n+1), []
for _ in range(m): orders.append([int(x) for x in input().split()])
orders.sort()
for i in range(m):
t, id = orders[i][0], orders[i][1]
if last[id]!=t:
score[id] -= t-last[id]-1
if score[id]<0: score[id]=0
if score[id]<=3: st[id]=0
score[id] += 2
if score[id]>5: st[id]=1
last[id]=t
for i in range(1,n+1):
if last[i]<T:
score[i] -= T-last[i]
if score[i]<=3: st[i]=0
res = 0
for i in range(1,n+1): res+=st[i]
print(res)
# acwing 1241. 外卖店优先级
# 自己写的纯暴力做法,超时了
if __name__ == '__main__':
n, m, t = map(int, input().split())
qprior, allscore, things = [], [0]*(n+1), []
for _ in range(m):
things.append([int(x) for x in input().split()])
things.sort()
time = 1
q_thistime = set()
for items in things:
if items[0]>t: break
if items[0]>time:
for _ in range(items[0]-time):
for i in range(1,n+1):
if i not in q_thistime:
allscore[i] -= 1
if allscore[i]<0: allscore[i]=0
if i in qprior and allscore[i]<=3:
qprior.pop(qprior.index(i))
q_thistime.clear()
time = items[0]
allscore[items[1]] += 2
q_thistime.add(items[1])
if allscore[items[1]]>5 and items[1] not in qprior: qprior.append(items[1])
for i in range(1, n + 1):
if i not in q_thistime:
allscore[i] -= 1
if allscore[i] < 0: allscore[i] = 0
if i in qprior and allscore[i] <= 3:
qprior.pop(qprior.index(i))
print(len(qprior))
Day 23 (2022.1.23)
树状数组和线段树
如果不需要修改的话直接用前缀和最好,但需要修改的话就要用树状数组了。
末尾有几个0,就在第几层
求和:
更新:
# acwing 1264. 动态求连续区间和
# 注意:区间下标要从1开始
def lowbit(x):
return x&-x
def add(x, v):
while x<=n:
tr[x] += v
x += lowbit(x)
def query(x):
res = 0
while x>=1:
res += tr[x]
x -= lowbit(x)
return res
if __name__ == '__main__':
n, m = map(int, input().split())
a, tr= [0] + [int(x) for x in input().split()], [0]*(n+1)
for i in range(1,n+1): add(i, a[i])
for _ in range(m):
k, x, y = map(int, input().split())
if k==0: print(query(y)-query(x-1))
else: add(x,y)
# acwing 1210. 连号区间数
# 遍历一维区间的子区间的两种方式
# 1. 按左端点遍历 for i in range(n): for j in range(i,n): [i:j]
# 2. 按右端点遍历 for i in range(n): for j in range(i,-1,-1): [j:i]
if __name__ == '__main__':
n = int(input())
a, res = [int(x) for x in input().split()], 0
for i in range(n):
a_max, a_min = a[i], a[i]
for j in range(i, n):
a_max, a_min = max(a_max, a[j]), min(a_min, a[j])
if j-i==a_max-a_min: res += 1
print(res)
if __name__ == '__main__':
n = int(input())
a, res = [int(x) for x in input().split()], 0
for i in range(n):
a_max, a_min = a[i], a[i]
for j in range(i,-1,-1):
a_max, a_min = max(a_max, a[j]), min(a_min, a[j])
if i-j==a_max-a_min: res += 1
print(res)
Day 24 (2022.1.24)
# acwing 1265. 数星星
N = 32010
def lowbit(x):
return x&-x
def add(x, v):
while x<=N:
tr[x] += v
x += lowbit(x)
def query(x):
res = 0
while x>=1:
res += tr[x]
x -= lowbit(x)
return res
if __name__ == '__main__':
n = int(input())
tr, level = [0]*N, [0]*N
for i in range(1,n+1):
x, y = map(int, input().split())
x += 1
level[query(x)] += 1
add(x, 1)
for i in range(n): print(level[i])
# acwing 1264. 动态求连续区间和
N = 100010
# 利用两个儿子来计算当前节点信息
def pushup(u):
tr[u][2] = tr[u*2][2] + tr[u*2+1][2]
def build(u, l, r):
# 当前已经是叶子节点,则直接存储相关信息
if l==r: tr[u] = [l, r, w[r]]
# 否则需要继续划分为两个区间
else:
# 给左右边界赋初值
tr[u][0], tr[u][1] = l, r
mid = (l + r)//2
build(u*2, l, mid)
build(u*2+1, mid+1, r)
# 两个儿子更新完后就记得更新下当前节点信息
pushup(u)
def query(u, l, r):
# 注意这个函数的第二、三参数和build的不同
# 如果当前区间已经被完全包含了,则直接返回
if tr[u][0]>=l and tr[u][1]<=r: return tr[u][2]
mid = (tr[u][0] + tr[u][1]) // 2
sum = 0
if l<=mid: sum = query(u*2, l, r)
if r>mid: sum += query(u*2+1, l, r)
return sum
def modify(u, x, v):
if tr[u][0] == tr[u][1]: tr[u][2] += v
else:
mid = (tr[u][0] + tr[u][1]) // 2
if x<=mid: modify(u*2, x, v)
else: modify(u*2+1, x, v)
pushup(u)
if __name__ == '__main__':
n, m = map(int, input().split())
w, tr = [0] + [int(x) for x in input().split()], [[0]*3 for _ in range(4*N)]
# 初始化时传入根节点下标,初始化区间1 - n
build(1, 1, n)
for _ in range(m):
k, a, b = map(int, input().split())
# 求和时传入根节点编号和查询区间端点
if k==0: print(query(1, a, b))
# 修改时传入根节点编号,修改参数的位置和更新数值
else: modify(1, a, b)
Day 25 (2022.1.25)
# acwing 1270. 数列区间最大值
N = 100010
def build(u,l,r):
if l==r: tr[u] = [l,r,w[r]]
else:
tr[u][0], tr[u][1] = l, r
mid = (l+r)//2
build(u*2,l,mid)
build(u*2+1,mid+1,r)
tr[u][2] = max(tr[u*2][2], tr[u*2+1][2])
def query(u,l,r):
if tr[u][0]>=l and tr[u][1]<=r: return tr[u][2]
else:
mid = (tr[u][0] + tr[u][1]) // 2
max_v = 0
if l<=mid: max_v = query(u*2,l,r)
if r>mid: max_v = max(max_v, query(u*2+1,l,r))
return max_v
if __name__ == '__main__':
n, m = map(int, input().split())
w, tr = [0] + [int(x) for x in input().split()], [[0]*3 for _ in range(4*N)]
build(1,1,n)
for _ in range(m):
a, b = map(int, input().split())
print(query(1,a,b))
Day 26 (2022.1.27)
用冒泡排序(逆序对)的思想,想要得到一个排好序的队列,有k个逆序对则至少要交换k次。
假设每一个小朋友他前面有k1个比他高,后面有k2个比他矮,那么他至少要交换k1+k2次才能够使得队列排序正确,怎样证明他只需要k1+k2次就可以使得队列排序正确呢,我们可以知道所有小朋友共交换2k(每个小朋友的交换次数都多算了一倍)(因为每次都只交换逆序对,所以是可以取到k的),而这个k就是逆序对的数量(一个逆序对需要调换两个小朋友的位置,因此小朋友会有2k次被影响),因此,可以取到k1+k2,要交换的次数就是k1+k2。
# acwing 1215. 小朋友排队
N = 1000010
def lowbit(x):
return x&-x
def add(x, v):
while x<=N-1:
tr[x] += v
x += lowbit(x)
def query(x):
ans = 0
while x>=1:
ans += tr[x]
x -= lowbit(x)
return ans
if __name__ == '__main__':
n = int(input())
arr, tr = [0] + [int(x)+1 for x in input().split()], [0]*N
sum = [0]*(n+1)
# 计算在他前面,但比他大的数
for i in range(1,n+1):
sum[i] += query(N-1) - query(arr[i])
add(arr[i],1)
tr = [0]*N
# 计算在他后面,但比他小的数
for i in range(n,0,-1):
sum[i] += query(arr[i]-1)
add(arr[i], 1)
res = 0
for i in range(1,n+1):
res += sum[i]*(sum[i]+1)//2
print(res)
Day 27 (2022.1.28)
最外层右上角点为4k^2,然后再求到这个点的曼哈顿距离
# acwing 1237. 螺旋折线
if __name__ == '__main__':
x, y = map(int, input().split())
k = max(abs(x), abs(y))
if x>=y: print((2*k)**2 + abs(x - k) + abs(y - k))
else: print((2*k)**2 - abs(x - k) - abs(y - k))
Day 28 (2022.1.30)
解题思路和代码实现还是有差别的,解题思路又是对思路细节的一些优化。
# acwing 1238. 日志统计
N = 100010
if __name__ == '__main__':
n, d, k = map(int, input().split())
logs, cnt, st = [], [0]*N, [0]*N
for _ in range(n): logs.append([int(x) for x in input().split()])
logs.sort()
i, j = 0, 0
while i<n:
ts, id = logs[i]
cnt[id] += 1
while ts-logs[j][0]>=d:
cnt[logs[j][1]] -= 1
j += 1
if cnt[id]>=k: st[id] = 1
i += 1
for i in range(N):
if st[i]: print(i)
Day 29 (2022.1.31)
今天复习799. 最长连续不重复子序。记录一堆东西是否有出现过可以用set、数组和字典,其中后两者可以记录其出现次数。
Day 30 (2022.2.3)
# acwing 1101. 献给阿尔吉侬的花束
from collections import deque
directions = [(1,0),(0,1),(0,-1),(-1,0)]
def bfs(start, end):
q = deque([start])
while q:
x, y = q.popleft()
for direction in directions:
x_mov, y_mov = x+direction[0], y+direction[1]
if x_mov>=1 and x_mov<=r and y_mov>=1 and y_mov<=c and dist[x_mov][y_mov]==0 and arr[x_mov][y_mov]!='#':
dist[x_mov][y_mov] = dist[x][y]+1
if [x_mov,y_mov] == end: return dist[x_mov][y_mov]
q.append([x_mov,y_mov])
return 'oop!'
if __name__ == '__main__':
t = int(input())
for _ in range(t):
r, c = map(int, input().split())
arr, dist = ['#'*(c+1)], [[0]*(c+1) for _ in range(r+1)]
for _ in range(r):
arr.append('#'+input())
start, end = [], []
for i in range(1,r+1):
for j in range(1,c+1):
if arr[i][j]=='S': start = [i,j]
if arr[i][j]=='E': end = [i,j]
res = bfs(start, end)
print(res)