├── .gitignore ├── bellman_ford.py ├── binary_search_tree.py ├── bipartite_match.py ├── dfs.py ├── dijkstra.py ├── floyd_warshall.py ├── graph.py ├── histogram.py ├── kmp.py ├── kruskal.py ├── lca.py ├── lis.py ├── network_flow.py ├── number.py ├── permutation.py ├── scc.py ├── segment_tree.py ├── topological_sort.py ├── union_find.py ├── utility.py └── vector.py /.gitignore: -------------------------------------------------------------------------------- 1 | test.py 2 | input.in 3 | output.out -------------------------------------------------------------------------------- /bellman_ford.py: -------------------------------------------------------------------------------- 1 | def bellman_ford(graph, src): 2 | dist = {} 3 | for v in graph.V: 4 | dist[v] = int(1e9) 5 | dist[src] = 0 6 | updated = True 7 | count = 0 8 | while updated: 9 | count += 1 10 | if count > len(graph): 11 | return None 12 | updated = False 13 | for u in graph: 14 | if dist[u] == int(1e9): 15 | continue 16 | for v, c in graph[u]: 17 | if dist[u] + c < dist[v]: 18 | updated = True 19 | dist[v] = dist[u] + c 20 | return dist 21 | -------------------------------------------------------------------------------- /binary_search_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.left = None 4 | self.right = None 5 | self.data = data 6 | 7 | def insert(self, data): 8 | if self.data: 9 | if data < self.data: 10 | if self.left is None: 11 | self.left = Node(data) 12 | else: 13 | self.left.insert(data) 14 | elif data > self.data: 15 | if self.right is None: 16 | self.right = Node(data) 17 | else: 18 | self.right.insert(data) 19 | else: 20 | self.data = data 21 | 22 | def lookup(self, data, parent=None): 23 | if data < self.data: 24 | if self.left is None: 25 | return None, None 26 | return self.left.lookup(data, self) 27 | elif data > self.data: 28 | if self.right is None: 29 | return None, None 30 | return self.right.lookup(data, self) 31 | else: 32 | return self, parent 33 | 34 | def delete(self, data): 35 | node, parent = self.lookup(data) 36 | if node is not None: 37 | children_count = node.children_count() 38 | if children_count == 0: 39 | if parent: 40 | if parent.left is node: 41 | parent.left = None 42 | else: 43 | parent.right = None 44 | del node 45 | else: 46 | self.data = None 47 | elif children_count == 1: 48 | if node.left: 49 | n = node.left 50 | else: 51 | n = node.right 52 | if parent: 53 | if parent.left is node: 54 | parent.left = n 55 | else: 56 | parent.right = n 57 | del node 58 | else: 59 | self.left = n.left 60 | self.right = n.right 61 | self.data = n.data 62 | else: 63 | parent = node 64 | successor = node.right 65 | while successor.left: 66 | parent = successor 67 | successor = node.left 68 | node.data = successor.data 69 | if parent.left == successor: 70 | parent.left = successor.right 71 | else: 72 | parent.right = successor.right 73 | 74 | def children_count(self): 75 | cnt = 0 76 | if self.left: 77 | cnt += 1 78 | if self.right: 79 | cnt += 1 80 | return cnt 81 | 82 | def print_tree(self): 83 | if self.left: 84 | self.left.print_tree() 85 | print(self.data) 86 | if self.right: 87 | self.right.print_tree() 88 | 89 | -------------------------------------------------------------------------------- /bipartite_match.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | # Hopcroft Karp's Bipartite Match Algorihm 5 | # This code is based on pseudo code of Wikipedia. 6 | # Time complexity is sqrt(V) * E where V is # of nodes and E is # of edges. 7 | class BipartiteMatch: 8 | def __init__(self, U, V, adj): 9 | self.U = U 10 | self.V = V 11 | self.adj = adj 12 | self.pair_u = [-1 for _ in range(U)] 13 | self.pair_v = [-1 for _ in range(V)] 14 | self.dist = [0 for _ in range(U + 1)] 15 | 16 | def bfs(self): 17 | q = deque() 18 | for u in range(self.U): 19 | if self.pair_u[u] == -1: 20 | self.dist[u] = 0 21 | q.append(u) 22 | else: 23 | self.dist[u] = int(1e9) 24 | self.dist[self.U] = int(1e9) 25 | while q: 26 | u = q.popleft() 27 | if self.dist[u] < self.dist[self.U]: 28 | for v in range(self.V): 29 | if self.adj[u][v]: 30 | if self.dist[self.pair_v[v]] == int(1e9): 31 | self.dist[self.pair_v[v]] = self.dist[u] + 1 32 | q.append(self.pair_v[v]) 33 | return self.dist[self.U] != int(1e9) 34 | 35 | def dfs(self, u): 36 | if u != -1: 37 | for v in range(self.V): 38 | if self.adj[u][v]: 39 | if self.dist[self.pair_v[v]] == self.dist[u] + 1: 40 | if self.dfs(self.pair_v[v]): 41 | self.pair_v[v] = u 42 | self.pair_u[u] = v 43 | return True 44 | self.dist[u] = int(1e9) 45 | return False 46 | return True 47 | 48 | def match(self): 49 | size = 0 50 | while self.bfs(): 51 | for u in range(self.U): 52 | if self.pair_u[u] == -1: 53 | if self.dfs(u): 54 | size += 1 55 | return size 56 | -------------------------------------------------------------------------------- /dfs.py: -------------------------------------------------------------------------------- 1 | def reachable(graph, src, dst): 2 | visited = {} 3 | for v in graph.V: 4 | visited[v] = False 5 | stack = [src] 6 | visited[src] = True 7 | while stack: 8 | u = stack.pop() 9 | if u in graph: 10 | for v in graph[u]: 11 | if not visited[v]: 12 | stack.append(v) 13 | visited[v] = True 14 | if v == dst: 15 | return True 16 | return False 17 | -------------------------------------------------------------------------------- /dijkstra.py: -------------------------------------------------------------------------------- 1 | from heapq import heappush, heappop 2 | 3 | 4 | def dijkstra(graph, src): 5 | N = len(graph) 6 | dist = {graph.V[x]: -1 for x in range(N)} 7 | dist[src] = 0 8 | pq = [] 9 | heappush(pq, (0, src)) 10 | while pq: 11 | cost, u = heappop(pq) 12 | if 0 <= dist[u] < cost or not graph[u]: 13 | continue 14 | 15 | for v, c in graph[u]: 16 | next_dist = cost + c 17 | if dist[v] == -1 or dist[v] > next_dist: 18 | dist[v] = next_dist 19 | heappush(pq, (next_dist, v)) 20 | return dist 21 | -------------------------------------------------------------------------------- /floyd_warshall.py: -------------------------------------------------------------------------------- 1 | def floyd_warshall(N, adj): 2 | dist = [[int(1e9) for _ in range(N + 1)] for _ in range(N + 1)] 3 | for i in range(1, N + 1): 4 | dist[i][i] = 0 5 | for u in adj: 6 | for v, c in adj[u]: 7 | dist[u][v] = c 8 | for k in range(1, N + 1): 9 | for i in range(1, N + 1): 10 | if dist[i][k] == int(1e9): 11 | continue 12 | for j in range(1, N + 1): 13 | dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) 14 | return dist 15 | -------------------------------------------------------------------------------- /graph.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | def __init__(self, V): 3 | self.V = V 4 | self.E = {} 5 | 6 | def __setitem__(self, key, value): 7 | if key not in self.E: 8 | self.E[key] = [] 9 | self.E[key].append(value) 10 | 11 | def __getitem__(self, item): 12 | if item not in self.E: 13 | return [] 14 | else: 15 | return self.E[item] 16 | 17 | def __len__(self): 18 | return len(self.V) 19 | 20 | def __repr__(self): 21 | return repr(self.E) 22 | 23 | def __contains__(self, item): 24 | return item in self.E 25 | 26 | def __iter__(self): 27 | return iter(self.E) 28 | -------------------------------------------------------------------------------- /histogram.py: -------------------------------------------------------------------------------- 1 | def get_max_box(histogram): 2 | ans = 0 3 | stack = [(-1, 0)] 4 | histogram += [0] 5 | for i in range(len(histogram)): 6 | h = histogram[i] 7 | last_pos = i 8 | while stack and h <= stack[-1][1]: 9 | ans = max(ans, stack[-1][1] * (i - stack[-1][0])) 10 | last_pos = stack[-1][0] 11 | stack.pop() 12 | stack.append((last_pos, h)) 13 | return ans 14 | -------------------------------------------------------------------------------- /kmp.py: -------------------------------------------------------------------------------- 1 | # String submatching 2 | # find N from H 3 | # the function 'search' returns the list of matched index 4 | 5 | class KMP: 6 | def __init__(self, H, N): 7 | self.H = H 8 | self.N = N 9 | self.submatch = [0 for _ in range(len(N))] 10 | 11 | def get_submatch(self): 12 | begin = 1 13 | matched = 0 14 | while begin + matched < len(self.N): 15 | if self.N[begin + matched] == self.N[matched]: 16 | matched += 1 17 | self.submatch[begin + matched - 1] = matched 18 | else: 19 | if matched == 0: 20 | begin += 1 21 | else: 22 | begin += matched - self.submatch[matched - 1] 23 | matched = self.submatch[matched - 1] 24 | 25 | def search(self): 26 | self.get_submatch() 27 | ans = [] 28 | begin, matched = 0, 0 29 | while begin <= len(self.H) - len(self.N): 30 | if matched < len(self.N) and self.H[begin + matched] == self.N[matched]: 31 | matched += 1 32 | if matched == len(self.N): 33 | ans.append(begin) 34 | else: 35 | if matched == 0: 36 | begin += 1 37 | else: 38 | begin += matched - self.submatch[matched - 1] 39 | matched = self.submatch[matched - 1] 40 | return ans 41 | -------------------------------------------------------------------------------- /kruskal.py: -------------------------------------------------------------------------------- 1 | from graph import Graph 2 | from union_find import UnionFind 3 | 4 | 5 | # Kruskal's minimum spanning tree algorithm 6 | def kruskal(graph): 7 | ret = 0 8 | result = [] 9 | edges = [] 10 | for u in graph: 11 | for v, c in graph[u]: 12 | edges.append((u, v, c)) 13 | edges.sort(key=lambda x: x[2]) 14 | uf = UnionFind(len(graph.V)) 15 | 16 | for u, v, c in edges: 17 | if uf.find(u) == uf.find(v): 18 | continue 19 | uf.union(u, v) 20 | result.append((u, v)) 21 | ret += c 22 | 23 | return ret, result 24 | -------------------------------------------------------------------------------- /lca.py: -------------------------------------------------------------------------------- 1 | # Lowest Common Ancestor 2 | class LCA: 3 | def __init__(self, graph): 4 | self.graph = graph 5 | self.depth = {graph.V[x]: 0 for x in range(0, len(graph))} 6 | self.ancestor = {graph.V[x]: [] for x in range(0, len(graph))} 7 | self.dfs() 8 | 9 | def get_ancestor(self, u, p): 10 | self.ancestor[u].append(p) 11 | i = 1 12 | while self.depth[u] - 2**i >= 0: 13 | temp = self.ancestor[u][i - 1] 14 | self.ancestor[u].append(self.ancestor[temp][i - 1]) 15 | i += 1 16 | 17 | def dfs(self): 18 | self.depth[None] = -1 19 | stack = [(1, None)] 20 | while stack: 21 | u, p = stack.pop() 22 | self.depth[u] = self.depth[p] + 1 23 | self.get_ancestor(u, p) 24 | if u in self.graph: 25 | for v in self.graph[u]: 26 | if v != p: 27 | stack.append((v, u)) 28 | 29 | def get(self, u, v): 30 | if self.depth[u] != self.depth[v]: 31 | if self.depth[u] > self.depth[v]: 32 | u, v = v, u 33 | for i in range(len(self.ancestor[v]) - 1, -1, -1): 34 | if self.depth[u] <= self.depth[v] - 2**i: 35 | v = self.ancestor[v][i] 36 | 37 | ans = u 38 | if u != v: 39 | for i in range(len(self.ancestor[u]) - 1, -1, -1): 40 | if self.depth[u] - 2**i >= 0: 41 | if self.ancestor[u][i] != self.ancestor[v][i]: 42 | u = self.ancestor[u][i] 43 | v = self.ancestor[v][i] 44 | else: 45 | ans = self.ancestor[u][i] 46 | return ans 47 | -------------------------------------------------------------------------------- /lis.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect_right 2 | 3 | 4 | # Longest Increasing Sub-sequence 5 | def get_lis_size(seq): 6 | result = [seq[0]] 7 | for n in seq: 8 | if n > result[-1]: 9 | result.append(n) 10 | else: 11 | index = bisect_right(result, n) 12 | if index > 0 and result[index - 1] == n: 13 | continue 14 | result[index] = n 15 | 16 | return len(result) 17 | 18 | 19 | def get_lis(seq): 20 | lis_size = [1 for _ in range(len(seq))] 21 | prev = [-1 for _ in range(len(seq))] 22 | 23 | for i in range(1, len(seq)): 24 | for j in range(i): 25 | if seq[i] > seq[j]: 26 | lis_size[i] = max(lis_size[i], lis_size[j] + 1) 27 | prev[i] = j 28 | 29 | max_lis_size = 0 30 | index = -1 31 | for i in range(len(seq)): 32 | if lis_size[i] > max_lis_size: 33 | max_lis_size = lis_size[i] 34 | index = i 35 | 36 | result = [] 37 | while index >= 0: 38 | result.append(seq[index]) 39 | index = prev[index] 40 | return list(reversed(result)) 41 | -------------------------------------------------------------------------------- /network_flow.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | class NetworkFlow: 5 | def __init__(self, N, capacity): 6 | self.N = N 7 | self.capacity = capacity 8 | 9 | def bfs(self, flow, source, sink): 10 | parent = [-1 for _ in range(self.N)] 11 | q = deque() 12 | parent[source] = source 13 | q.append(source) 14 | while q and parent[sink] == -1: 15 | u = q.popleft() 16 | for v in range(self.N): 17 | if self.capacity[u][v] - flow[u][v] > 0 and parent[v] == -1: 18 | q.append(v) 19 | parent[v] = u 20 | return parent 21 | 22 | def max_flow(self, source, sink): 23 | flow = [[0 for _ in range(self.N)] for _ in range(self.N)] 24 | total_flow = 0 25 | while True: 26 | parent = self.bfs(flow, source, sink) 27 | if parent[sink] == -1: 28 | break 29 | amount = int(1e9) 30 | p = sink 31 | while p != source: 32 | amount = min(amount, self.capacity[parent[p]][p] - flow[parent[p]][p]) 33 | p = parent[p] 34 | p = sink 35 | while p != source: 36 | flow[parent[p]][p] += amount 37 | flow[p][parent[p]] -= amount 38 | p = parent[p] 39 | total_flow += amount 40 | return total_flow 41 | -------------------------------------------------------------------------------- /number.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | 4 | def gcd(a, b): 5 | if a > b: 6 | a, b = b, a 7 | if a == 0: 8 | return b 9 | else: 10 | return gcd(b % a, a) 11 | 12 | 13 | def lcd(a, b): 14 | return a * b // gcd(a, b) 15 | 16 | 17 | class Fibonacci: 18 | def __init__(self, P=0): 19 | self.m = [[1, 1], [1, 0]] 20 | self.P = P 21 | 22 | def matmul(self, m1, m2): 23 | if self.P == 0: 24 | return [[(m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0]), (m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1])], 25 | [(m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0]), (m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1])]] 26 | else: 27 | return [[(m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0]) % self.P, (m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1]) % self.P], 28 | [(m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0]) % self.P, (m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1]) % self.P]] 29 | 30 | def pow(self, m, n): 31 | if n == 1: 32 | return m 33 | if n % 2 == 1: 34 | return self.matmul(self.pow(m, n - 1), m) 35 | else: 36 | p = self.pow(m, n//2) 37 | return self.matmul(p, p) 38 | 39 | def get(self, n): 40 | if n == 0: 41 | return 0 42 | m = self.pow(self.m, n) 43 | return m[1][0] 44 | 45 | 46 | def factor(n): 47 | ans = set([]) 48 | for i in range(1, int(sqrt(n)) + 1): 49 | if n % i == 0: 50 | ans.add(i) 51 | ans.add(n // i) 52 | return ans 53 | 54 | 55 | def get_prime(N): 56 | prime = [True for _ in range(N + 1)] 57 | prime[0] = False 58 | prime[1] = False 59 | for n in range(2, int(sqrt(N)) + 1): 60 | if prime[n]: 61 | for k in range(n*2, N + 1, n): 62 | prime[k] = False 63 | return {n for n in range(2, N + 1) if prime[n]} 64 | 65 | 66 | def factorize(prime, n): 67 | ans = {} 68 | for p in prime: 69 | while n % p == 0: 70 | if p not in ans: 71 | ans[p] = 0 72 | ans[p] += 1 73 | n //= p 74 | if n == 1: 75 | return ans 76 | -------------------------------------------------------------------------------- /permutation.py: -------------------------------------------------------------------------------- 1 | def unique_permutations_helper(occurences, result, d): 2 | if d == 0: 3 | yield result 4 | else: 5 | for i in range(4): 6 | if occurences[i] > 0: 7 | result.append(i) 8 | occurences[i] -= 1 9 | for g in unique_permutations_helper(occurences, result, d - 1): 10 | yield g 11 | occurences[i] += 1 12 | result.pop() 13 | 14 | 15 | def unique_permutations(occurences): 16 | result = [] 17 | d = sum(occurences) 18 | return unique_permutations_helper(occurences, result, d) 19 | 20 | 21 | def get_next_permutation(seq): 22 | length = len(seq) 23 | for i in range(length - 2, -1, -1): 24 | if seq[i] < seq[i + 1]: 25 | break 26 | else: 27 | return [-1] 28 | 29 | min_value = length + 1 30 | min_index = i 31 | for j in range(i + 1, length): 32 | if seq[i] < seq[j] < min_value: 33 | min_value = seq[j] 34 | min_index = j 35 | seq[i], seq[min_index] = seq[min_index], seq[i] 36 | tail = sorted(seq[i + 1:]) 37 | for j in range(i + 1, length): 38 | seq[j] = tail[j - i - 1] 39 | return seq 40 | 41 | 42 | def get_prev_permutation(seq): 43 | length = len(seq) 44 | for i in range(length - 2, -1, -1): 45 | if seq[i] > seq[i + 1]: 46 | break 47 | else: 48 | return [-1] 49 | 50 | max_value = 0 51 | max_index = i 52 | for j in range(i + 1, length): 53 | if max_value < seq[j] < seq[i]: 54 | max_value = seq[j] 55 | max_index = j 56 | seq[i], seq[max_index] = seq[max_index], seq[i] 57 | tail = sorted(seq[i + 1:], reverse=True) 58 | for j in range(i + 1, length): 59 | seq[j] = tail[j - i - 1] 60 | return seq 61 | 62 | 63 | -------------------------------------------------------------------------------- /scc.py: -------------------------------------------------------------------------------- 1 | # Strongly Connected Components 2 | def strongly_connected_components(graph): 3 | identified = set() 4 | stack = [] 5 | index = {} 6 | boundaries = [] 7 | 8 | for v in graph.V: 9 | if v not in index: 10 | to_do = [('VISIT', v)] 11 | while to_do: 12 | operation_type, v = to_do.pop() 13 | if operation_type == 'VISIT': 14 | index[v] = len(stack) 15 | stack.append(v) 16 | boundaries.append(index[v]) 17 | to_do.append(('POSTVISIT', v)) 18 | # We reverse to keep the search order identical to that of 19 | # the recursive code; the reversal is not necessary for 20 | # correctness, and can be omitted. 21 | to_do.extend(reversed([('VISITEDGE', w) for w in graph[v]])) 22 | elif operation_type == 'VISITEDGE': 23 | if v not in index: 24 | to_do.append(('VISIT', v)) 25 | elif v not in identified: 26 | while index[v] < boundaries[-1]: 27 | boundaries.pop() 28 | else: 29 | # operation_type == 'POSTVISIT' 30 | if boundaries[-1] == index[v]: 31 | boundaries.pop() 32 | scc = set(stack[index[v]:]) 33 | del stack[index[v]:] 34 | identified.update(scc) 35 | yield scc 36 | -------------------------------------------------------------------------------- /segment_tree.py: -------------------------------------------------------------------------------- 1 | class SegmentTree: 2 | def __init__(self, start, end, data): 3 | self.start = start 4 | self.end = end 5 | self.data = data 6 | self.max_value = {} 7 | self.min_value = {} 8 | self.sum_value = {} 9 | self.len_value = {} 10 | self._init(start, end) 11 | 12 | def add(self, start, end, weight=1): 13 | start = max(start, self.start) 14 | end = min(end, self.end) 15 | self._add(start, end, weight, self.start, self.end) 16 | return True 17 | 18 | def query_max(self, start, end): 19 | return self._query_max(start, end, self.start, self.end) 20 | 21 | def query_min(self, start, end): 22 | return self._query_min(start, end, self.start, self.end) 23 | 24 | def query_sum(self, start, end): 25 | return self._query_sum(start, end, self.start, self.end) 26 | 27 | def query_len(self, start, end): 28 | return self._query_len(start, end, self.start, self.end) 29 | 30 | def _init(self, start, end): 31 | if start < end: 32 | mid = start + int((end - start) / 2) 33 | max_l, min_l, sum_l, len_l = self._init(start, mid) 34 | max_r, min_r, sum_r, len_r = self._init(mid + 1, end) 35 | self.max_value[(start, end)] = max(max_l, max_r) 36 | self.min_value[(start, end)] = min(min_l, min_r) 37 | self.sum_value[(start, end)] = sum_l + sum_r 38 | self.len_value[(start, end)] = len_l + len_r 39 | else: 40 | a = self.data[start - self.start] 41 | self.max_value[(start, end)] = a 42 | self.min_value[(start, end)] = a 43 | self.sum_value[(start, end)] = a 44 | if a == 0: 45 | self.len_value[(start, end)] = 0 46 | else: 47 | self.len_value[(start, end)] = 1 48 | 49 | return self.max_value[(start, end)], self.min_value[(start, end)], self.sum_value[(start, end)], self.len_value[(start, end)] 50 | 51 | def _add(self, start, end, weight, in_start, in_end): 52 | key = (in_start, in_end) 53 | if in_start == in_end: 54 | self.max_value[key] += weight 55 | self.min_value[key] += weight 56 | self.sum_value[key] += weight 57 | self.len_value[key] = 1 if self.sum_value[key] > 0 else 0 58 | return 59 | 60 | mid = in_start + int((in_end - in_start) / 2) 61 | if mid >= end: 62 | self._add(start, end, weight, in_start, mid) 63 | elif mid+1 <= start: 64 | self._add(start, end, weight, mid+1, in_end) 65 | else: 66 | self._add(start, mid, weight, in_start, mid) 67 | self._add(mid+1, end, weight, mid+1, in_end) 68 | self.max_value[key] = max(self.max_value[(in_start, mid)], self.max_value[(mid+1, in_end)]) 69 | self.min_value[key] = min(self.min_value[(in_start, mid)], self.min_value[(mid+1, in_end)]) 70 | self.sum_value[key] = self.sum_value[(in_start, mid)] + self.sum_value[(mid+1, in_end)] 71 | self.len_value[key] = self.len_value[(in_start, mid)] + self.len_value[(mid+1, in_end)] 72 | 73 | def _query_max(self, start, end, in_start, in_end): 74 | if start == in_start and end == in_end: 75 | ans = self.max_value[(start, end)] 76 | else: 77 | mid = in_start + int((in_end - in_start) / 2) 78 | if mid >= end: 79 | ans = self._query_max(start, end, in_start, mid) 80 | elif mid+1 <= start: 81 | ans = self._query_max(start, end, mid+1, in_end) 82 | else: 83 | ans = max(self._query_max(start, mid, in_start, mid), 84 | self._query_max(mid+1, end, mid+1, in_end)) 85 | return ans 86 | 87 | def _query_min(self, start, end, in_start, in_end): 88 | if start == in_start and end == in_end: 89 | ans = self.min_value[(start, end)] 90 | else: 91 | mid = in_start + int((in_end - in_start) / 2) 92 | if mid >= end: 93 | ans = self._query_min(start, end, in_start, mid) 94 | elif mid+1 <= start: 95 | ans = self._query_min(start, end, mid+1, in_end) 96 | else: 97 | ans = min(self._query_min(start, mid, in_start, mid), 98 | self._query_min(mid+1, end, mid+1, in_end)) 99 | return ans 100 | 101 | def _query_sum(self, start, end, in_start, in_end): 102 | if start == in_start and end == in_end: 103 | ans = self.sum_value[(start, end)] 104 | else: 105 | mid = in_start + int((in_end - in_start) / 2) 106 | if mid >= end: 107 | ans = self._query_sum(start, end, in_start, mid) 108 | elif mid+1 <= start: 109 | ans = self._query_sum(start, end, mid+1, in_end) 110 | else: 111 | ans = self._query_sum(start, mid, in_start, mid) + self._query_sum(mid+1, end, mid+1, in_end) 112 | return ans 113 | 114 | def _query_len(self, start, end, in_start, in_end): 115 | if start == in_start and end == in_end: 116 | ans = self.len_value[(start, end)] 117 | else: 118 | mid = in_start + int((in_end - in_start) / 2) 119 | if mid >= end: 120 | ans = self._query_len(start, end, in_start, mid) 121 | elif mid+1 <= start: 122 | ans = self._query_len(start, end, mid+1, in_end) 123 | else: 124 | ans = self._query_len(start, mid, in_start, mid) + self._query_len(mid+1, end, mid+1, in_end) 125 | 126 | return ans 127 | 128 | 129 | # Segment Tree implemented by myself. 130 | class SimpleSegTree: 131 | def __init__(self, left, right): 132 | self.left = left 133 | self.right = right 134 | self.tree = [0 for i in range(4 * (right - left + 1))] 135 | stack = [(1, left, right)] 136 | while len(stack) > 0: 137 | index, left, right = stack.pop() 138 | self.tree[index] = right - left + 1 139 | if right > left: 140 | middle = (left + right) // 2 141 | stack.append((index * 2, left, middle)) 142 | stack.append((index * 2 + 1, middle + 1, right)) 143 | 144 | def query(self, left, right): 145 | stack = [(1, self.left, self.right)] 146 | if left > right: 147 | left, right = right, left 148 | sum = 0 149 | while len(stack) > 0: 150 | index, seg_left, seg_right = stack.pop() 151 | if left <= seg_left and right >= seg_right: 152 | sum += self.tree[index] 153 | elif seg_right < left or seg_left > right: 154 | continue 155 | else: 156 | middle = (seg_left + seg_right) // 2 157 | stack.append((index * 2, seg_left, middle)) 158 | stack.append((index * 2 + 1, middle + 1, seg_right)) 159 | return sum 160 | 161 | def _add(self, num, d): 162 | index = 1 163 | seg_left = self.left 164 | seg_right = self.right 165 | while seg_right > seg_left: 166 | self.tree[index] += d 167 | middle = (seg_left + seg_right) // 2 168 | if num <= middle: 169 | seg_right = middle 170 | index *= 2 171 | else: 172 | seg_left = middle + 1 173 | index = index * 2 + 1 174 | 175 | self.tree[index] += d 176 | 177 | def delete(self, num): 178 | self._add(num, -1) 179 | 180 | def add(self, num): 181 | self._add(num, 1) 182 | 183 | 184 | from math import ceil, log2 185 | 186 | 187 | class SegmentTreeWithLazyPropagation: 188 | def __init__(self, data): 189 | self.N = len(data) 190 | h = int(ceil(log2(self.N))) 191 | self.tree_size = (1 << (h + 1)) - 1 192 | self.tree = [0 for _ in range(self.tree_size)] 193 | self.lazy = [0 for _ in range(self.tree_size)] 194 | self._init(data, 1, 0, self.N - 1) 195 | 196 | def _init(self, data, node, start, end): 197 | if start == end: 198 | self.tree[node] = data[start] 199 | else: 200 | self.tree[node] = self._init(data, node*2, start, (start + end)//2) +\ 201 | self._init(data, node*2 + 1, (start + end)//2 + 1, end) 202 | return self.tree[node] 203 | 204 | def _update_lazy(self, node, start, end): 205 | if self.lazy[node] != 0: 206 | self.tree[node] += (end - start + 1)*self.lazy[node] 207 | if start != end: 208 | self.lazy[node*2] += self.lazy[node] 209 | self.lazy[node*2 + 1] += self.lazy[node] 210 | self.lazy[node] = 0 211 | 212 | def _update_range(self, node, start, end, left, right, diff): 213 | self._update_lazy(node, start, end) 214 | if left > end or right < start: 215 | return 216 | if left <= start and end <= right: 217 | self.tree[node] += (end - start + 1)*diff 218 | if start != end: 219 | self.lazy[node*2] += diff 220 | self.lazy[node*2 + 1] += diff 221 | return 222 | self._update_range(node*2, start, (start + end)//2, left, right, diff) 223 | self._update_range(node*2 + 1, (start + end)//2 + 1, end, left, right, diff) 224 | self.tree[node] = self.tree[node*2] + self.tree[node*2 + 1] 225 | 226 | def update_range(self, left, right, diff): 227 | self._update_range(1, 0, self.N - 1, left, right, diff) 228 | 229 | def _sum(self, node, start, end, left, right): 230 | self._update_lazy(node, start, end) 231 | if left > end or right < start: 232 | return 0 233 | if left <= start and end <= right: 234 | return self.tree[node] 235 | return self._sum(node*2, start, (start + end)//2, left, right) + \ 236 | self._sum(node*2 + 1, (start + end)//2 + 1, end, left, right) 237 | 238 | def sum(self, left, right): 239 | return self._sum(1, 0, self.N - 1, left, right) 240 | 241 | 242 | # FenwickTree (Binary Indexed Tree) with point update and range query 243 | # the index is 1~N 244 | class FenwickTree: 245 | def __init__(self, size): 246 | self.size = size 247 | self.tree = [0] 248 | for i in range(1, size+1): 249 | self.tree.append(i & -i) 250 | 251 | def sum(self, n): 252 | ans = 0 253 | while n > 0: 254 | ans += self.tree[n] 255 | n &= n-1 256 | return ans 257 | 258 | def query(self, left, right): 259 | if left > right: 260 | left, right = right, left 261 | return self.sum(right) - self.sum(left-1) 262 | 263 | def _add(self, pos, d): 264 | while pos <= self.size: 265 | self.tree[pos] += d 266 | pos += (pos & -pos) 267 | 268 | def add(self, pos): 269 | self._add(pos, 1) 270 | 271 | def delete(self, pos): 272 | self._add(pos, -1) 273 | 274 | 275 | # FenwickTree (Binary Indexed Tree) with range update and point query 276 | # the index is 0~N-1 277 | class FenwickTreeRangeUpdate: 278 | def __init__(self, data): 279 | self.data = data 280 | self.N = len(data) 281 | self.ft = [0 for _ in range(self.N + 1)] 282 | 283 | def update(self, p, v): 284 | p += 1 285 | while p <= self.N: 286 | self.ft[p] += v 287 | p += p & (-p) 288 | 289 | def update_range(self, a, b, v): 290 | self.update(a, v) 291 | self.update(b + 1, -v) 292 | 293 | def query(self, a): 294 | sum = 0 295 | b = a + 1 296 | while b > 0: 297 | sum += self.ft[b] 298 | b -= b & (-b) 299 | return sum + self.data[a] 300 | -------------------------------------------------------------------------------- /topological_sort.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | def topological_sort(graph): 5 | N = len(graph) 6 | in_degree = {graph.V[x]: 0 for x in range(N)} 7 | for u in graph: 8 | for v in graph[u]: 9 | in_degree[v] += 1 10 | q = deque() 11 | for v in in_degree: 12 | if in_degree[v] == 0: 13 | q.append(v) 14 | 15 | result = [] 16 | while q: 17 | u = q.pop() 18 | result.append(u) 19 | if u in graph: 20 | for v in graph[u]: 21 | in_degree[v] -= 1 22 | if in_degree[v] == 0: 23 | q.append(v) 24 | if len(result) != N: 25 | return [] 26 | else: 27 | return result 28 | -------------------------------------------------------------------------------- /union_find.py: -------------------------------------------------------------------------------- 1 | class UnionFind: 2 | def __init__(self, N): 3 | self.tree = [i for i in range(N + 1)] 4 | 5 | def find(self, n): 6 | list = [] 7 | p = self.tree[n] 8 | while p != n: 9 | list.append(n) 10 | n = p 11 | p = self.tree[n] 12 | 13 | for n in list: 14 | self.tree[n] = p 15 | 16 | return p 17 | 18 | def union(self, n, m): 19 | p = self.find(n) 20 | q = self.find(m) 21 | self.tree[q] = p 22 | -------------------------------------------------------------------------------- /utility.py: -------------------------------------------------------------------------------- 1 | dd = [(-1, 0), (0, 1), (1, 0), (0, -1)] 2 | def neighbor(N, M, y, x): 3 | ans = [] 4 | for dy, dx in dd: 5 | y1, x1 = y + dy, x + dx 6 | if y1 < 0 or y1 >= N or x1 < 0 or x1 >= M: 7 | continue 8 | ans.append((y1, x1)) 9 | return ans 10 | 11 | 12 | def parametric_search_max(f, left, right): 13 | ans = 0 14 | while left < right: 15 | middle = (left + right) // 2 16 | if f(middle): 17 | ans = max(ans, middle) 18 | left = middle + 1 19 | else: 20 | right = middle 21 | 22 | if f(left): 23 | ans = max(ans, left) 24 | 25 | return ans 26 | 27 | 28 | def parametric_search_min(f, left, right): 29 | ans = int(1e9) 30 | while left < right: 31 | middle = (left + right) // 2 32 | if f(middle): 33 | ans = min(ans, middle) 34 | right = middle 35 | else: 36 | left = middle + 1 37 | 38 | if f(left): 39 | ans = min(ans, left) 40 | 41 | return ans 42 | -------------------------------------------------------------------------------- /vector.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | EPSILON = 1e-7 5 | 6 | 7 | class Vector: 8 | def __init__(self, x, y): 9 | self.x , self.y = x, y 10 | 11 | def __eq__(self, other): 12 | return (self.x, self.y) == (other.x, other.y) 13 | 14 | def __add__(self, other): 15 | return Vector(self.x + other.x, self.y + other.y) 16 | 17 | def __sub__(self, other): 18 | return Vector(self.x - other.x, self.y - other.y) 19 | 20 | def __mul__(self, other): 21 | return Vector(self.x * other, self.y * other) 22 | 23 | def __lt__(self, other): 24 | return self.x < other.x if self.x != other.x else self.y < other.y 25 | 26 | def __gt__(self, other): 27 | return self.x > other.x if self.x != other.x else self.y > other.y 28 | 29 | def __le__(self, other): 30 | return self < other or self == other 31 | 32 | def __ge__(self, other): 33 | return self > other or self == other 34 | 35 | def norm(self): 36 | return math.hypot(self.x, self.y) 37 | 38 | def normalize(self): 39 | n = self.norm() 40 | return Vector(self.x / n, self.y / n) 41 | 42 | def polar(self): 43 | return math.fmod(math.atan2(self.y, self.x) + 2*math.pi, 2*math.pi) 44 | 45 | def dot(self, other): 46 | return self.x*other.x + self.y + other.y 47 | 48 | def cross(self, other): 49 | return self.x*other.y - other.x*self.y 50 | 51 | def project(self, other): 52 | other = other.normalize() 53 | return other * other.dot(self) 54 | 55 | 56 | def triangle_area(a, b, c): 57 | return abs((b-a).cross(c-a)) / 2 58 | 59 | 60 | def ccw(p, a, b): # returns positive if b is counter-clockwise of a 61 | return (a - p).cross(b - p) 62 | 63 | 64 | def intersection(a, b, c, d): # returns intersection of line(a, b) and line(c, d). returns None if they are parallel 65 | det = (b - a).cross(d - c) 66 | if (abs(det)) < EPSILON: 67 | return None 68 | return a + (b - a)*((c - a).cross(d - c) / det) 69 | 70 | 71 | def convex_hull(points): 72 | p0 = min(points) 73 | index = points.index(p0) 74 | points[0], points[index] = points[index], points[0] 75 | points = points[:1] + sorted(points[1:], key=lambda a: (int(1e9) if a.x == p0.x else (a.y - p0.y) / (a.x - p0.x), a.x, a.y)) 76 | 77 | hull = [] 78 | for p in points: 79 | while len(hull) >= 2 and ccw(hull[-2], hull[-1], p) <= 0: 80 | hull.pop() 81 | hull.append(p) 82 | return hull 83 | --------------------------------------------------------------------------------