## Python チートシート
入力
```jsx
3
1 2 3
4 5 6
7 8 9
n = int(stdin.readline().rstrip())
data = [stdin.readline().rstrip().split() for _ in range(n)]
1 2 3
data = [int(x) for x in stdin.readline().rstrip().split()]
```
配列
```python
l = [1, 2, 3, 4, 5]
print(l[0])
//1
print(l[-1])
//5
print(l[:3])
[1, 2, 3]
print(l[-3:])
[3, 4, 5]
print(l[1:4])
[2,3,4]
リストの要素の追加(最後に追加)
l.append(600)
リストの要素の追加(先頭に追加:0番目のインデックスに「0」を追加)
l.insert(0, 0)
リストの要素の取得(最後の要素の取得、リストからは消える)
l.pop()
リストの要素の取得(0番目の要素の削除、リストからは消える)
l.pop(0)
リストの指定した値に合致した要素を削除
l.remove(3)
リストの要素数の取得
print(len(l))
指定した値に合致するインデックスの取得
l.index(3)
//2
```
dict
```python
d = {'x': 10, 'y': 20, 'z': 30}
辞書型(ディクショナリ型)にキーと値の追加
d['a'] = 40
辞書型(ディクショナリ型)の特定のキーの削除
del d['a']
辞書型(ディクショナリ型)のキーリストの取得
list(d.keys())
特定のキーの値を取得
d['x']
```
deque
```python
S = deque()
一番上(最後尾)に要素追加
S.append(x)
一番上の要素取得
a = S[-1]
一番上の要素を削除
a = S.pop()
先頭要素を取得
a = S[0]
先頭要素を削除
a= S.popleft()
```
heapq(優先度つきqueue)
```python
T = []
追加
heapq.heappush(T,x)
最小値を取得し、削除
a = heapq.heappop(T)
```
set
```python
S = set()
set.add(x)
set.remove(x)
```
制御
```python
if 条件式1:
条件式1が真の場合に実行される処理
elif 条件式2:
条件式1が偽かつ条件式2が真の場合に実行される処理
else:
全ての条件式が偽の場合に実行される処理
1 != 1
1 >= 0
1 <= 0
and
or
items = ['pen', 'note', 'book']
'book' in items
'note' not in items
```
ループ
```python
for i in list:
for i in range(int):
chars = 'word'
for count, char in enumerate(chars):
print(f'{count}番目の文字は{char}')
sports = {'baseball': 9, 'soccer': 11, 'tennis': 2}
for k, v in sports.items():
```
関数
```python
def increment(num1, num2):
return a, b //配列で返す
```
class
```python
class Person:
def __init__(self):
print('Init completed!')
def say_something(self):
print('Hello!!!')
person = Person()
```
## 二分探索priter
```python
# 答えが x 以下かを判定し、Yes であれば true、No であれば false を返す関数
def check(x, N, K, A):
sum = 0
for i in range(N):
sum += x // A[i] # 「x÷A[i]」の小数点以下切り捨て
if sum >= K:
return True
return False
# 二分探索
# Left は探索範囲の左端を、Right は探索範囲の右端を表す
Left = 1
Right = 10 ** 9
while Left < Right:
Mid = (Left + Right) // 2
Answer = check(Mid, N, K, A)
if Answer == False:
Left = Mid + 1 # 答えが Mid+1 以上であることが分かる
if Answer == True:
Right = Mid # 答えが Mid 以下であることが分かる
# 出力(このとき Left=Right になっている)
print(Left)
```
## 二分探索木
```python
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BST:
def __init__(self, arr):
self.root = None
for val in arr:
self.insert(val)
def insert(self, val):
if self.root is None:
self.root = Node(val)
else:
node = self.root
flag = True
while flag:
if node.data > val:
if node.left is None:
node.left = Node(val)
flag = False
# whileを終了させるためにFalseをセットする
else:
node = node.left
else:
if node.right is None:
node.right = Node(val)
flag = False
else:
node = node.right
def find(self, node, val):
if node is not None:
if node.data == val:
return True
else:
flag_left = self.find(node.left, val)
flag_right = self.find(node.right, val)
if flag_left or flag_right:
return True
return False
def bst_min(self, node):
if node.left is None:
return node.data
else:
return self.bst_min(node.left)
#再帰で行きついた先の値を返したいときはreturn のあとに再帰関数を書く。traversalのときと用法が異なるので注意。
def bst_max(self, node):
if node.right is None:
return node.data
else:
return self.bst_max(node.right)
def inoder_traverse(self, node):
if node is not None:
self.inoder_traverse(node.left)
print(node.data)
self.inoder_traverse(node.right)
```
## dungeon
```python
# 動的計画法
dp = [ None ] * (N+1)
dp[1] = 0
dp[2] = A[0]
for i in range(3, N+1):
dp[i] = min(dp[i-1]+A[i-2], dp[i-2]+B[i-3])
# 答えの復元
# 変数 Place は現在位置(ゴールから進んでいく)
# たとえば入力例の場合、Place は 5 → 4 → 2 → 1 と変化していく
Answer = []
Place = N
while True:
Answer.append(Place)
if Place == 1:
break
# どこから部屋 Place に向かうのが最適かを求める
if dp[Place-1] + A[Place-2] == dp[Place]:
Place = Place - 1
else:
Place = Place - 2
Answer.reverse()
```
## subset sum
```python
0 1 2 3 4 5 6 7
0 T F F F F F F F
1 T F T F F F F F
2 T F T F T F F F
3 T F T T T T F T
dp = [ [ None ] * (S + 1) for i in range(N + 1) ]
dp[0][0] = True
for i in range(1, S+1):
dp[0][i] = False
# 動的計画法(i=1)
for i in range(1, N+1):
for j in range(0,S+1):
if j < A[i-1]:
if dp[i-1][j] == True:
dp[i][j] = True
else:
dp[i][j] = False
if j >= A[i-1]:
if dp[i-1][j] == True or dp[i-1][j-A[i-1]] == True:
dp[i][j] = True
else:
dp[i][j] = False
```
## knapsack
```
w = [ None ] * (N + 1)
v = [ None ] * (N + 1)
for i in range(1, N+1):
w[i], v[i] = map(int, input().split())
# 動的計画法
dp = [ [ -10 ** 15 ] * (W + 1) for i in range(N + 1) ]
dp[0][0] = 0
for i in range(1, N+1):
for j in range(0,W+1):
if j < w[i]:
dp[i][j] = dp[i-1][j]
if j >= w[i]:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
```
## Longest Common Subsequence
```python
dp = [ [ None ] * (M + 1) for i in range(N + 1) ]
dp[0][0] = 0
for i in range(0, N+1):
for j in range(0,M+1):
if i>=1 and j>=1 and S[i-1]==T[j-1]:
dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]+1)
elif i>=1 and j>=1:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
elif i>=1:
dp[i][j] = dp[i-1][j]
elif j>=1:
dp[i][j] = dp[i][j-1]
```
## 配る遷移方式
```
dp = [ -(10 ** 9) ] * (N + 1)
dp[1] = 0
# 動的計画法
for i in range(1, N):
dp[A[i-1]] = max(dp[A[i-1]], dp[i] + 100)
dp[B[i-1]] = max(dp[B[i-1]], dp[i] + 150)
```
## bit DP
```python
# 配列の初期化
dp = [ [ 10 ** 9 ] * (2 ** N) for i in range(M + 1) ]
# 動的計画法
dp[0][0] = 0
for i in range(1, M+1):
for j in range(0, 2 ** N):
# already[k] = 1 のとき、品物 k は既に無料になっている
already = [ None ] * N
for k in range(0, N):
if (j // (2 ** k)) % 2 == 0:
already[k] = 0
else:
already[k] = 1
# クーポン券 i を選んだ場合の整数表現 v を計算する
v = 0
for k in range(0, N):
if already[k] == 1 or A[i-1][k] == 1:
v += (2 ** k)
# 遷移を行う
dp[i][j] = min(dp[i][j], dp[i-1][j])
dp[i][v] = min(dp[i][v], dp[i-1][j] + 1)
```
## deep first search
```python
def dfs(pos, G, searched_flag_list):
searched_flag_list[pos] = True
for nex in G[pos]:
if nex == True:
pass
else:
dfs(nex, G, searched_flag_list)
def solve(n, m, connected_list):
G = [list() for i in range(N)]
for a,b in connected_list:
G[a].append(b)
G[b].append(a)
searched_flag_list = [False] * (N + 1)
dfs(1,G,searched_flag_list)
answer = True
for i in range(1, N+1):
if searched_flag_list[i] == False:
answer = False
```
## breadth first search
```
G = [ list() for i in range(N + 1) ]
for a, b in edges:
G[a].append(b)
G[b].append(a)
# 幅優先探索の初期化(dist[i] = ? ではなく dist[i] = -1 で初期化していることに注意)
dist = [ -1 ] * (N + 1)
dist[1] = 0
Q = deque()
Q.append(1)
# 幅優先探索
while len(Q) >= 1:
pos = Q.popleft() # キュー Q の先頭要素を取り除き、その値を pos に代入する
for nex in G[pos]:
if dist[nex] == -1:
dist[nex] = dist[pos] + 1
Q.append(nex)
```
## ダイクストラ法
```python
# 隣接リストの作成(重み付きグラフなので、各辺について (隣接頂点, 重み) のタプルを記録する)
G = [ list() for i in range(N + 1) ]
for a, b, c in edges:
G[a].append((b, c))
G[b].append((a, c))
# 配列・キューの初期化(キューには (距離, 頂点番号) のタプルを記録する)
INF = 10 ** 10
kakutei = [ False ] * (N + 1)
cur = [ INF ] * (N + 1)
cur[1] = 0
Q = []
heapq.heappush(Q, (cur[1], 1))
# ダイクストラ法
while len(Q) >= 1:
# 次に確定させるべき頂点を求める
# (ここでは、優先度付きキュー Q の最小要素を取り除き、その要素の 2 番目の値(頂点番号)を pos に代入する)
pos = heapq.heappop(Q)[1]
# Q の最小要素が「既に確定した頂点」の場合
if kakutei[pos] == True:
continue
# cur[x] の値を更新する
kakutei[pos] = True
for e in G[pos]:
# 書籍内のコードとは pos = e[0], cost = e[1] で対応している
if cur[e[0]] > cur[pos] + e[1]:
cur[e[0]] = cur[pos] + e[1]
heapq.heappush(Q, (cur[e[0]], e[0]))
```
## DP tree
```python
A = [ 0 ] * 2 + list(map(int, input().split()))
# 隣接リストの作成
G = [ list() for i in range(N + 1) ]
for i in range(2, N + 1):
G[A[i]].append(i) # 上司 → 部下の方向に方向に辺を追加
# 動的計画法(dp[x] は社員 x の部下の数)
dp = [ 0 ] * (N + 1)
for i in range(N, 0, -1):
for j in G[i]:
dp[i] += (dp[j] + 1)
```
## union-find
```python
class unionfind:
def __init__(self, n):
self.n = n
self.par = [ -1 ] * (n+1)
self.size = [1] * (n+1)
def root(self, x):
while self.par[x] != 1:
x = self.par[x]
return x
def unite(self, u, v):
rootu = self.root(u)
rootv = self.root(v)
if rootu != rootv:
if self.size[rootu] < self.size[rootv]:
self.par[rootu] = rootv
self.size[rootv] += self.size[rootu]
else:
self.par[rootv] = rootu
self.size[rooty] += self.size[rootv]
def same(self, u, v):
return self.root(u) == self.root(v)
```