├── .gitignore ├── README.md ├── advance ├── README.md └── cses1628.cpp ├── cpp-stl ├── README.md ├── template.cpp └── template.md ├── data-structures ├── 487B.cpp ├── 487B_2.cpp ├── 597C.cpp ├── DQUERY.cpp ├── README.md ├── cses1144.cpp ├── cses_1143.cpp ├── cses_1144.cpp ├── cses_1190.cpp ├── cses_1646.cpp ├── cses_1647.cpp ├── cses_1648.cpp ├── cses_1648_sqrt.cpp ├── cses_1649.cpp ├── cses_1650.cpp ├── cses_1651.cpp ├── cses_1652.cpp ├── cses_1734.cpp ├── cses_1734_2.cpp ├── cses_1735.cpp ├── cses_1736.cpp ├── cses_1739.cpp ├── cses_2166.cpp ├── cses_2206.cpp ├── cses_2416.cpp ├── fwk-tree │ └── README.md ├── lqd_querysum.cpp ├── rmq-lca │ ├── lca.cpp │ └── rmq_min.cpp ├── segtree_template.cpp ├── test.cpp ├── vnoi_gss.cpp ├── vnoi_segtree_itez1.cpp ├── vnoi_segtree_itez2.cpp └── vnoi_segtree_itlazy.cpp ├── dynamic-programming ├── CSES-DP.md ├── README.md ├── bitmap │ └── cses_1690.cpp ├── cses_1093.cpp ├── cses_1097.cpp ├── cses_1097_02.cpp ├── cses_1097_03.cpp ├── cses_1140.cpp ├── cses_1145.cpp ├── cses_1158.cpp ├── cses_1633.cpp ├── cses_1634.cpp ├── cses_1635.cpp ├── cses_1636.cpp ├── cses_1637.cpp ├── cses_1637_02.cpp ├── cses_1638.cpp ├── cses_1639.cpp ├── cses_1653.cpp ├── cses_1744.cpp ├── cses_1745.cpp ├── cses_1746.cpp ├── cses_2181.cpp ├── cses_2220.cpp ├── cses_2413.cpp ├── digit_cf_628.cpp ├── digit_cf_6282.cpp ├── number_13.cpp ├── spoj_PR003004.cpp └── string_number_13.cpp ├── graph-theory ├── README.md ├── articulation_points_and_bridges.cpp ├── binary_search_2d.cpp ├── bridges_duplicate.cpp ├── cs-matrix.cpp ├── cses_1096.cpp ├── cses_1130.cpp ├── cses_1131.cpp ├── cses_1132.cpp ├── cses_1133.cpp ├── cses_1135.cpp ├── cses_1136.cpp ├── cses_1137.cpp ├── cses_1138.cpp ├── cses_1139.cpp ├── cses_1160.cpp ├── cses_1192.cpp ├── cses_1193.cpp ├── cses_1194.cpp ├── cses_1195.cpp ├── cses_1195_02.cpp ├── cses_1196.cpp ├── cses_1197.cpp ├── cses_1197_2.cpp ├── cses_1202.cpp ├── cses_1666.cpp ├── cses_1667.cpp ├── cses_1668.cpp ├── cses_1669.cpp ├── cses_1671.cpp ├── cses_1672.cpp ├── cses_1673.cpp ├── cses_1674.cpp ├── cses_1675.cpp ├── cses_1678.cpp ├── cses_1679.cpp ├── cses_1680.cpp ├── cses_1681.cpp ├── cses_1682.cpp ├── cses_1682_2.cpp ├── cses_1683.cpp ├── cses_1683_02.cpp ├── cses_1684.cpp ├── cses_1686.cpp ├── cses_1687.cpp ├── cses_1688.cpp ├── cses_1689.cpp ├── cses_1691.cpp ├── cses_1692.cpp ├── cses_1694.cpp ├── cses_1694_2.cpp ├── cses_1695.cpp ├── cses_1696.cpp ├── cses_1696_2.cpp ├── cses_1711.cpp ├── cses_1723.cpp ├── cses_1724.cpp ├── cses_1750.cpp ├── cses_1751.cpp ├── cses_2079.cpp ├── cses_2080.cpp ├── cses_2134.cpp ├── dsu │ ├── 468B.cpp │ ├── 722C.cpp │ ├── a │ ├── cs-mountain-time.cpp │ ├── cs-mt2.cpp │ ├── cses1676.cpp │ ├── cses_2101.cpp │ ├── dsu.cpp │ ├── test.cpp │ ├── usaco16_g2.cpp │ └── usaco_1259.cpp ├── floyd_warshall.cpp ├── graph-cses.md ├── love_song_csl.cpp ├── nkflow.cpp ├── scc.cpp └── test_flow.cpp ├── intro ├── cses_1068.cpp ├── cses_1069.cpp ├── cses_1070.cpp ├── cses_1071.cpp ├── cses_1072.cpp ├── cses_1083.cpp ├── cses_1092.cpp ├── cses_1094.cpp ├── cses_1617.cpp ├── cses_1618.cpp ├── cses_1622.cpp ├── cses_1623.cpp ├── cses_1624.cpp ├── cses_1625.cpp ├── cses_1754.cpp ├── cses_1755.cpp ├── cses_2165.cpp ├── cses_2205.cpp ├── cses_2220.cpp └── cses_2431.cpp ├── machine-learning ├── README.md ├── ai4-purpose.md ├── artificial-intelligence.md ├── computer-vision.md ├── data-analytic-business.md ├── data-science.md ├── neural-network.md ├── nlp.md ├── robotics.md ├── speech.md └── time-series.md ├── mathematics ├── README.md ├── combinatorics.md ├── cses-problem.md ├── cses1079.cpp ├── cses1081.md ├── cses1082.cpp ├── cses1082.md ├── cses1712-phi-euler.md ├── cses1712.cpp ├── cses1713.md ├── cses1715.cpp ├── cses1716.cpp ├── cses1717.cpp ├── cses1722.cpp ├── cses2064.cpp ├── cses2064.md ├── cses2164.cpp ├── cses2182.cpp ├── cses2182.md ├── cses2189.cpp ├── cses2190.cpp ├── cses2191.cpp ├── cses2192.cpp ├── cses2194.cpp ├── cses2195.cpp ├── cses2195_2.cpp ├── cses_1081.cpp ├── cses_1095.cpp ├── cses_1712.cpp ├── cses_1713.cpp ├── cses_1725.cpp ├── cses_2185.cpp ├── cses_2210.cpp ├── cses_2417.cpp ├── eratosthenes.cpp ├── game-theory.md ├── geometry.md ├── number-theory.md ├── ternary_578C.cpp ├── ternary_building.cpp ├── test.cpp └── test.py ├── string-algorithms ├── 1990C.cpp ├── README.md ├── censoring.cpp ├── cses_1110.cpp ├── cses_1111.cpp ├── cses_1112.cpp ├── cses_165B.cpp ├── cses_1731.cpp ├── cses_1732.cpp ├── cses_1733.cpp ├── cses_1733_2.cpp ├── cses_1733_3.cpp ├── cses_1753.cpp ├── cses_2102.cpp ├── cses_2103.cpp ├── cses_2104.cpp ├── cses_2108.cpp ├── cses_2420.cpp ├── hash.cpp └── hash.md ├── training-topic ├── README.md ├── code-sub-task │ ├── README.md │ ├── sumn │ └── sumn.cpp ├── common_technique.md ├── dsa-book.md ├── geometry.md ├── miscellaneous_algo.md ├── product-gen │ ├── README.md │ ├── problem_solution.cpp │ ├── product_check.sh │ ├── product_gen.cpp │ └── product_slow.cpp ├── sorting-and-searching │ ├── README.md │ ├── a │ ├── built-in.cpp │ ├── cses_1073.cpp │ ├── cses_1074.cpp │ ├── cses_1076.cpp │ ├── cses_1084.cpp │ ├── cses_1085.cpp │ ├── cses_1090.cpp │ ├── cses_1091.cpp │ ├── cses_1141.cpp │ ├── cses_1163.cpp │ ├── cses_1164.cpp │ ├── cses_1619.cpp │ ├── cses_1620.cpp │ ├── cses_1621.cpp │ ├── cses_1629.cpp │ ├── cses_1630.cpp │ ├── cses_1631.cpp │ ├── cses_1632.cpp │ ├── cses_1640.cpp │ ├── cses_1641.cpp │ ├── cses_1642.cpp │ ├── cses_1643.cpp │ ├── cses_1644.cpp │ ├── cses_1645.cpp │ ├── cses_1660.cpp │ ├── cses_1661.cpp │ ├── cses_1662.cpp │ ├── cses_2162.cpp │ ├── cses_2168.cpp │ ├── cses_2169.cpp │ ├── cses_2183.cpp │ ├── cses_2216.cpp │ ├── cses_2428.cpp │ └── searching.md ├── stdc++.h ├── test-case-generator.md └── tip-and-tricks.md └── usaco-guide └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.in 3 | *.out 4 | *.ans 5 | *.diff 6 | *.tmp 7 | *.exe 8 | *.o 9 | *.inp 10 | *.out 11 | *.ans 12 | .DS_Store 13 | */a 14 | clean_text.ipynb 15 | dethi01/ 16 | *.zip 17 | tmp/ 18 | ebooks/ 19 | bao-cva/ -------------------------------------------------------------------------------- /cpp-stl/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | // Uncomment the lines below for fast input/output 9 | #define fast_io ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 10 | // #define endl '\n' 11 | 12 | typedef long long ll; 13 | typedef vector vi; 14 | typedef pair pii; 15 | 16 | #define INF 1000000000 17 | #define FOR(i, a, b) for (int i = (a); i < (b); ++i) 18 | #define FORR(i, a, b) for (int i = (a); i >= (b); --i) 19 | #define REP(i, n) FOR(i, 0, n) 20 | #define REPR(i, n) FORR(i, n, 0) 21 | #define TR(c, it) for (auto it = (c).begin(); it != (c).end(); ++it) 22 | 23 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 24 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 25 | #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } 26 | 27 | #define DEBUG(x) cerr << #x << " = " << x << endl; 28 | #define DEBUG_ARRAY(arr, n) { REP(i, n) cerr << arr[i] << " "; cerr << endl; } 29 | 30 | int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } 31 | int lcm(int a, int b) { return a / gcd(a, b) * b; } 32 | 33 | int main() { 34 | // adding fast_io for fast input/output 35 | fast_io; 36 | 37 | // Your code here 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /data-structures/487B_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace std; 26 | 27 | typedef long long int64; 28 | typedef unsigned long long uint64; 29 | #define two(X) (1<<(X)) 30 | #define twoL(X) (((int64)(1))<<(X)) 31 | #define contain(S,X) (((S)&two(X))!=0) 32 | #define containL(S,X) (((S)&twoL(X))!=0) 33 | const double pi=acos(-1.0); 34 | const double eps=1e-11; 35 | template inline void checkmin(T &a,T b){if(b inline void checkmax(T &a,T b){if(b>a) a=b;} 37 | template inline T sqr(T x){return x*x;} 38 | typedef pair ipair; 39 | #define SIZE(A) ((int)A.size()) 40 | #define LENGTH(A) ((int)A.length()) 41 | #define MP(A,B) make_pair(A,B) 42 | #define PB(X) push_back(X) 43 | 44 | const int maxn=200000+10; 45 | const int INF=100000000; 46 | 47 | int n,l,d; 48 | int a[maxn]; 49 | int p[maxn]; 50 | int f[maxn]; 51 | 52 | int main() { 53 | 54 | scanf("%d%d%d",&n,&d,&l); 55 | for (int i=0;i S; 57 | for (int k=0,i=0;i=0) S.insert(f[i-l]); 75 | for (;k<=i-l && k=INF) f[n]=-1; 79 | printf("%d\n",f[n]); 80 | return 0; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /data-structures/597C.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ll long long 8 | using namespace std; 9 | const int MAXN = 1e5 + 5; 10 | vector bit[MAXN]; 11 | int n; 12 | 13 | ll get_sum(int l, int x) { 14 | ll ans = 0; 15 | for (int idx = x; idx > 0; idx -= idx & (-idx)) { 16 | ans += bit[l][idx]; 17 | } 18 | return ans; 19 | } 20 | 21 | void update(int l, int x, long long v) { 22 | for (int idx = x; idx < MAXN; idx += idx & (-idx)) { 23 | bit[l][idx] += v; 24 | } 25 | } 26 | 27 | int main() { 28 | int temp, k; 29 | ll kq = 0; 30 | cin >> n >> k; 31 | // cout << n << " " << k << endl; 32 | for (int i = 1; i <= k+2; i++) bit[i].resize(MAXN); 33 | 34 | k++; 35 | 36 | for (int i = 0; i < n; i++) { 37 | cin >> temp; 38 | update(1, temp, 1); 39 | for (int l = 2; l <= k; ++l) { 40 | ll m = get_sum(l-1, temp-1); 41 | // cout << i << " " << l << " " << m << endl; 42 | update(l, temp, m); 43 | } 44 | // kq += get_sum(k, temp); 45 | // cout << "Get: " << get_sum(k, temp) << endl; 46 | // cout << "---\n"; 47 | 48 | } 49 | cout << get_sum(k, n) << endl; 50 | return 0; 51 | } 52 | 53 | // g++ -std=c++17 -o a 597C.cpp && ./a < a.in -------------------------------------------------------------------------------- /data-structures/cses_1143.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int INF = 1e9+7; 8 | 9 | class SegmentTree { 10 | vector tree; 11 | int size; 12 | 13 | public: 14 | SegmentTree(int n) { 15 | size = n; 16 | tree.resize(2 * n, -1); 17 | } 18 | 19 | void build(const vector& arr) { 20 | for (int i = 0; i < size; ++i) { 21 | tree[size + i] = arr[i]; 22 | } 23 | for (int i = size - 1; i > 0; --i) { 24 | tree[i] = max(tree[2 * i], tree[2 * i + 1]); 25 | } 26 | } 27 | 28 | void update(int pos, int value) { 29 | pos += size; 30 | tree[pos] = value; 31 | while (pos > 1) { 32 | pos /= 2; 33 | tree[pos] = max(tree[2 * pos], tree[2 * pos + 1]); 34 | } 35 | } 36 | 37 | int query(int l, int r, int x) { 38 | l += size; 39 | r += size; 40 | while (l <= r) { 41 | if (l % 2 == 1 && tree[l] >= x) return l - size; 42 | if (r % 2 == 0 && tree[r] >= x) return r - size; 43 | l = (l + 1) / 2; 44 | r = (r - 1) / 2; 45 | } 46 | return -1; 47 | } 48 | }; 49 | 50 | int main() { 51 | int n, m; 52 | cin >> n >> m; 53 | 54 | vector hotels(n); 55 | for (int i = 0; i < n; ++i) { 56 | cin >> hotels[i]; 57 | } 58 | 59 | SegmentTree segTree(n); 60 | segTree.build(hotels); 61 | 62 | for (int i = 0; i < m; ++i) { 63 | int rooms_needed; 64 | cin >> rooms_needed; 65 | 66 | int index = segTree.query(0, n - 1, rooms_needed); 67 | if (index != -1) { 68 | cout << index + 1 << " "; 69 | hotels[index] -= rooms_needed; 70 | segTree.update(index, hotels[index]); 71 | } else { 72 | cout << 0 << " "; 73 | } 74 | } 75 | cout << endl; 76 | 77 | return 0; 78 | } 79 | 80 | // g++ -std=c++17 -o a cses_1143.cpp && ./a < a.in -------------------------------------------------------------------------------- /data-structures/cses_1646.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n, q; 8 | cin >> n >> q; 9 | 10 | vector arr(n + 1, 0); 11 | vector prefix_sum(n + 1, 0); 12 | 13 | // Reading the array 14 | for (int i = 1; i <= n; ++i) { 15 | cin >> arr[i]; 16 | } 17 | 18 | // Compute prefix sums 19 | for (int i = 1; i <= n; ++i) { 20 | prefix_sum[i] = prefix_sum[i - 1] + arr[i]; 21 | } 22 | 23 | // Process each query 24 | while (q--) { 25 | int a, b; 26 | cin >> a >> b; 27 | // Answer the query using the prefix sums array 28 | cout << prefix_sum[b] - prefix_sum[a - 1] << endl; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /data-structures/cses_1647.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class SegmentTree { 9 | public: 10 | SegmentTree(const vector& data) { 11 | n = data.size(); 12 | tree.assign(4 * n, INT_MAX); 13 | build(data, 0, 0, n - 1); 14 | } 15 | 16 | int query(int l, int r) { 17 | return query(0, 0, n - 1, l, r); 18 | } 19 | 20 | private: 21 | vector tree; 22 | int n; 23 | 24 | void build(const vector& data, int node, int start, int end) { 25 | if (start == end) { 26 | tree[node] = data[start]; 27 | } else { 28 | int mid = (start + end) / 2; 29 | build(data, 2 * node + 1, start, mid); 30 | build(data, 2 * node + 2, mid + 1, end); 31 | tree[node] = min(tree[2 * node + 1], tree[2 * node + 2]); 32 | } 33 | } 34 | 35 | int query(int node, int start, int end, int l, int r) { 36 | if (r < start || end < l) { 37 | return INT_MAX; 38 | } 39 | if (l <= start && end <= r) { 40 | return tree[node]; 41 | } 42 | int mid = (start + end) / 2; 43 | int left_min = query(2 * node + 1, start, mid, l, r); 44 | int right_min = query(2 * node + 2, mid + 1, end, l, r); 45 | return min(left_min, right_min); 46 | } 47 | }; 48 | 49 | int main() { 50 | int n, q; 51 | cin >> n >> q; 52 | 53 | vector data(n); 54 | for (int i = 0; i < n; ++i) { 55 | cin >> data[i]; 56 | } 57 | 58 | SegmentTree seg_tree(data); 59 | 60 | while (q--) { 61 | int a, b; 62 | cin >> a >> b; 63 | // Convert 1-based index to 0-based index 64 | cout << seg_tree.query(a - 1, b - 1) << endl; 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /data-structures/cses_1650.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n, q; 8 | cin >> n >> q; 9 | 10 | vector arr(n + 1, 0); 11 | vector prefix_xor(n + 1, 0); 12 | 13 | // Reading the array values 14 | for (int i = 1; i <= n; ++i) { 15 | cin >> arr[i]; 16 | } 17 | 18 | // Compute the prefix XOR array 19 | for (int i = 1; i <= n; ++i) { 20 | prefix_xor[i] = prefix_xor[i - 1] ^ arr[i]; 21 | } 22 | 23 | // Process each query 24 | while (q--) { 25 | int a, b; 26 | cin >> a >> b; 27 | // XOR sum from index a to b is prefix_xor[b] ^ prefix_xor[a - 1] 28 | cout << (prefix_xor[b] ^ prefix_xor[a - 1]) << endl; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /data-structures/cses_1652.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n, q; 8 | cin >> n >> q; 9 | 10 | vector> forest(n + 1, vector(n + 1, 0)); 11 | vector> prefix(n + 1, vector(n + 1, 0)); 12 | 13 | // Reading the forest map 14 | for (int i = 1; i <= n; ++i) { 15 | string row; 16 | cin >> row; 17 | for (int j = 1; j <= n; ++j) { 18 | forest[i][j] = (row[j-1] == '*'); 19 | } 20 | } 21 | 22 | // Building the prefix sum array 23 | for (int i = 1; i <= n; ++i) { 24 | for (int j = 1; j <= n; ++j) { 25 | prefix[i][j] = forest[i][j] + prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1]; 26 | } 27 | } 28 | 29 | // Answering the queries 30 | while (q--) { 31 | int y1, x1, y2, x2; 32 | cin >> y1 >> x1 >> y2 >> x2; 33 | 34 | int result = prefix[y2][x2] - prefix[y1-1][x2] - prefix[y2][x1-1] + prefix[y1-1][x1-1]; 35 | cout << result << endl; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /data-structures/cses_2416.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | ios_base::sync_with_stdio(false); 7 | cin.tie(0); 8 | 9 | int n, q; 10 | cin >> n >> q; 11 | 12 | vector arr(n + 1); 13 | for (int i = 1; i <= n; i++) { 14 | cin >> arr[i]; 15 | } 16 | 17 | // Difference array to calculate how much each element violates the increasing order 18 | vector operations(n + 1, 0); 19 | 20 | // Precompute the required operations for each pair of adjacent elements 21 | for (int i = 2; i <= n; i++) { 22 | if (arr[i] < arr[i - 1]) { 23 | operations[i] = arr[i - 1] - arr[i]; 24 | } 25 | } 26 | 27 | // Build a prefix sum array for the operations array 28 | vector prefix_sum(n + 1, 0); 29 | for (int i = 1; i <= n; i++) { 30 | prefix_sum[i] = prefix_sum[i - 1] + operations[i]; 31 | } 32 | 33 | // Process queries 34 | while (q--) { 35 | int a, b; 36 | cin >> a >> b; 37 | // The number of operations needed to make the subarray [a, b] increasing 38 | cout << prefix_sum[b] - prefix_sum[a] << "\n"; 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /data-structures/lqd_querysum.cpp: -------------------------------------------------------------------------------- 1 | // https://lqdoj.edu.vn/problem/querysum 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | const int N = 1e5 + 5; 11 | int n, q; 12 | long long a[N]; 13 | 14 | int main() { 15 | cin.tie(0)->sync_with_stdio(0); 16 | cin >> n >> q; 17 | 18 | // for (int i = 0; i < n; ++i) { 19 | // cin >> a[i]; 20 | // } 21 | n = 100; 22 | for (int i = 0; i < n; ++i) { 23 | cout << i << " " << (i & (-i)) << endl; 24 | // explain value of (i & (i)) 25 | 26 | } 27 | return 0; 28 | } 29 | 30 | // g++ -std=c++17 -o a lqd_querysum.cpp && ./a < a.in 31 | -------------------------------------------------------------------------------- /data-structures/rmq-lca/rmq_min.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class SparseTable { 7 | private: 8 | std::vector> st; 9 | std::vector log; 10 | 11 | public: 12 | SparseTable(const std::vector& arr) { 13 | int n = arr.size(); 14 | int K = log2(n) + 1; 15 | 16 | st.resize(n, std::vector(K)); 17 | log.resize(n + 1); 18 | 19 | // Precompute logs 20 | log[1] = 0; 21 | for (int i = 2; i <= n; i++) 22 | log[i] = log[i / 2] + 1; 23 | 24 | // Initialize Sparse Table for the intervals of length 1 25 | for (int i = 0; i < n; i++) 26 | st[i][0] = arr[i]; 27 | 28 | // Compute values from smaller to bigger intervals 29 | for (int j = 1; j <= K; j++) { 30 | for (int i = 0; (i + (1 << j)) <= n; i++) { 31 | st[i][j] = std::min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 32 | } 33 | } 34 | } 35 | 36 | int query(int L, int R) { 37 | int j = log[R - L + 1]; 38 | return std::min(st[L][j], st[R - (1 << j) + 1][j]); 39 | } 40 | }; 41 | 42 | int main() { 43 | std::vector arr = {1, 3, 2, 7, 9, 11}; 44 | SparseTable st(arr); 45 | 46 | std::cout << "Minimum value in range (1, 4): " << st.query(1, 4) << std::endl; // Output: 2 47 | std::cout << "Minimum value in range (0, 5): " << st.query(0, 5) << std::endl; // Output: 1 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /data-structures/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MOD = 998244353; 6 | 7 | int main() { 8 | int N; 9 | cin >> N; 10 | vector A(N + 1); 11 | for (int i = 1; i <= N; i++) { 12 | cin >> A[i]; 13 | } 14 | 15 | // dp[i] will store if we can paint square i black 16 | vector dp(N + 1, false); 17 | dp[1] = true; // initially only square 1 is black 18 | 19 | for (int i = 1; i <= N; i++) { 20 | if (!dp[i]) continue; // skip if we can't reach this square 21 | for (int j = i + A[i]; j <= N; j += A[i]) { 22 | dp[j] = true; 23 | } 24 | } 25 | 26 | // Now count how many distinct sets of squares can be painted black 27 | vector painted; 28 | for (int i = 1; i <= N; i++) { 29 | if (dp[i]) painted.push_back(i); 30 | } 31 | 32 | // The number of distinct sets that can be painted is the number of 33 | // different reachable squares. 34 | // Each dp[i] tells us if square i can be painted. 35 | int result = 1; 36 | for (int i = 0; i < painted.size(); i++) { 37 | result = (result * 2) % MOD; 38 | } 39 | 40 | cout << result << endl; 41 | 42 | return 0; 43 | } 44 | 45 | // g++ -std=c++11 -O2 -Wall test.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /data-structures/vnoi_gss.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | const int INF = 1e9 + 7; 6 | const int MAXN = 5e4 + 10; 7 | int n; 8 | 9 | struct Node { 10 | int pre, suf, sum, maxsum; 11 | 12 | Node(int pre = -INF, int suf = -INF, int sum = 0, int maxsum = -INF) : pre(pre), suf(suf), sum(sum), maxsum(maxsum) {} 13 | 14 | static Node merge(Node& a, Node& b) { 15 | return Node( 16 | max(a.pre, a.sum + b.pre), 17 | max(b.suf, b.sum + a.suf), 18 | a.sum + b.sum, 19 | // max({a.maxsum, b.maxsum, a.suf + b.pre}) 20 | max(max(a.maxsum, b.maxsum), a.suf + b.pre) 21 | ); 22 | } 23 | }; 24 | 25 | Node tree[4 * MAXN]; 26 | int arr[MAXN]; 27 | 28 | void build(int root, int start, int end) { 29 | if (start == end) { 30 | tree[root] = Node(arr[start], arr[start], arr[start], arr[start]); 31 | return; 32 | } 33 | int mid = (start + end) / 2; 34 | build(2 * root, start, mid); 35 | build(2 * root + 1, mid + 1, end); 36 | tree[root] = Node::merge(tree[2 * root], tree[2 * root + 1]); 37 | } 38 | 39 | 40 | 41 | Node queryRangeUtil(int start, int end, int l, int r, int node) { 42 | if (start > r || end < l) { 43 | return Node(); 44 | } 45 | 46 | if (start >= l && end <= r) { 47 | return tree[node]; 48 | } 49 | 50 | int mid = (start + end) / 2; 51 | Node left = queryRangeUtil(start, mid, l, r, 2 * node); 52 | Node right = queryRangeUtil(mid + 1, end, l, r, 2 * node + 1); 53 | return Node::merge(left, right); 54 | 55 | } 56 | 57 | 58 | int main() { 59 | cin.tie(0)->sync_with_stdio(0); 60 | cin >> n; 61 | for (int i = 0; i < n; i++) { 62 | cin >> arr[i]; 63 | } 64 | build(1, 0, n - 1); 65 | int q; 66 | cin >> q; 67 | while (q--) { 68 | int u, v; 69 | cin >> u >> v; 70 | cout << queryRangeUtil(0, n - 1, u - 1, v - 1, 1).maxsum << '\n'; 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | // g++ -std=c++17 -o a vnoi_gss.cpp && ./a < a.in -------------------------------------------------------------------------------- /data-structures/vnoi_segtree_itez2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | const int INF = 1e9; 6 | const int MAXN = 1e5 + 10; 7 | int n; 8 | 9 | long long tree[4 * MAXN]; 10 | 11 | 12 | void updatePoint(int start, int end, int idx, int val, int node) { 13 | if (start == end) { 14 | tree[node] = val; 15 | return; 16 | } 17 | int mid = (start + end) / 2; 18 | if (start <= idx && idx <= mid) { 19 | updatePoint(start, mid, idx, val, 2 * node); 20 | } else { 21 | updatePoint(mid + 1, end, idx, val, 2 * node + 1); 22 | } 23 | tree[node] = tree[2 * node] + tree[2 * node + 1]; 24 | } 25 | 26 | 27 | long long queryRangeUtil(int start, int end, int l, int r, int node) { 28 | 29 | if (start > end || start > r || end < l) 30 | return 0; 31 | 32 | if (start >= l && end <= r) 33 | return tree[node]; 34 | 35 | int mid = (start + end) / 2; 36 | long long leftSum = queryRangeUtil(start, mid, l, r, 2 * node); 37 | long long rightSum = queryRangeUtil(mid + 1, end, l, r, 2 * node + 1); 38 | return leftSum + rightSum; 39 | } 40 | 41 | 42 | int main() { 43 | cin.tie(0)->sync_with_stdio(0); 44 | cin >> n; 45 | memset(tree, 0, sizeof(tree)); 46 | 47 | int q; 48 | cin >> q; 49 | while (q--) { 50 | int type; 51 | cin >> type; 52 | if (type == 2) { 53 | int l, r; 54 | cin >> l >> r; 55 | l -= 1; 56 | r -= 1; 57 | cout << queryRangeUtil(0, n - 1, l, r, 1) << "\n"; 58 | } else { 59 | int idx, val; 60 | cin >> idx >> val; 61 | idx -= 1; 62 | updatePoint(0, n - 1, idx, val, 1); 63 | } 64 | } 65 | 66 | 67 | return 0; 68 | } 69 | 70 | // g++ -std=c++17 -o a vnoi_segtree_itez2.cpp && ./a < a.in 71 | -------------------------------------------------------------------------------- /dynamic-programming/bitmap/cses_1690.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | using ll = long long; 5 | 6 | const int MAX_N = 20; 7 | const ll MOD = (ll)1e9 + 7; 8 | 9 | ll dp[1 << MAX_N][MAX_N]; 10 | // come_from[i] contains the cities that can fly to i 11 | vector come_from[MAX_N]; 12 | 13 | int main() { 14 | int city_num; 15 | int flight_num; 16 | cin >> city_num >> flight_num; 17 | for (int f = 0; f < flight_num; f++) { 18 | int start, end; 19 | cin >> start >> end; 20 | come_from[--end].push_back(--start); 21 | } 22 | 23 | dp[1][0] = 1; 24 | for (int s = 2; s < 1 << city_num; s++) { 25 | // only consider subsets that have the first city 26 | if ((s & (1 << 0)) == 0) continue; 27 | // also only consider subsets with the last city if it's the full subset 28 | if ((s & (1 << (city_num - 1))) && s != ((1 << city_num) - 1)) continue; 29 | 30 | for (int end = 0; end < city_num; end++) { 31 | if ((s & (1 << end)) == 0) continue; 32 | 33 | // the subset that doesn't include the current end 34 | int prev = s - (1 << end); 35 | for (int j : come_from[end]) { 36 | if ((s & (1 << j))) { 37 | dp[s][end] += dp[prev][j]; 38 | dp[s][end] %= MOD; 39 | } 40 | } 41 | } 42 | } 43 | cout << dp[(1 << city_num) - 1][city_num - 1] << '\n'; 44 | } -------------------------------------------------------------------------------- /dynamic-programming/cses_1093.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | using namespace std; 7 | 8 | int countWaysToDivide(int n) { 9 | long long sum = (n * (n + 1)) / 2; 10 | 11 | // If sum is odd, we cannot split into two equal subsets 12 | if (sum % 2 != 0) return 0; 13 | 14 | long long target = sum / 2; 15 | vector dp(target + 1, 0); 16 | dp[0] = 1; // Base case: one way to make sum 0 17 | 18 | for (int i = 1; i <= n; ++i) { 19 | for (int j = target; j >= i; --j) { 20 | dp[j] = (dp[j] + dp[j - i]) % MOD; 21 | } 22 | } 23 | 24 | return (dp[target] * 500000004) % MOD; // Multiply by modular inverse of 2 to divide by 2 25 | } 26 | 27 | int main() { 28 | int n; 29 | cin >> n; 30 | 31 | cout << countWaysToDivide(n) << endl; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1097.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | vector x(n); 11 | for (int i = 0; i < n; ++i) { 12 | cin >> x[i]; 13 | } 14 | 15 | // dp[i][j] will store the maximum score difference (player1 - player2) for subarray [i, j] 16 | vector> dp(n, vector(n, 0)); 17 | 18 | // Base case: when the subarray is of length 1 19 | for (int i = 0; i < n; ++i) { 20 | dp[i][i] = x[i]; 21 | } 22 | 23 | // Fill the DP table for subarrays of length 2 up to n 24 | for (int len = 2; len <= n; ++len) { 25 | for (int i = 0; i <= n - len; ++i) { 26 | int j = i + len - 1; 27 | dp[i][j] = max(x[i] - dp[i+1][j], x[j] - dp[i][j-1]); 28 | } 29 | } 30 | 31 | // Calculate the maximum possible score for the first player 32 | long long total_sum = 0; 33 | for (int i = 0; i < n; ++i) { 34 | total_sum += x[i]; 35 | } 36 | long long max_score_difference = dp[0][n-1]; 37 | long long first_player_max_score = (total_sum + max_score_difference) / 2; 38 | 39 | cout << first_player_max_score << endl; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1097_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | int n; 7 | 8 | // Recursive function with memoization to calculate the maximum score difference 9 | long long maxScoreDifference(int i, int j, const vector& x, vector>& dp) { 10 | if (i > j) return 0; 11 | if (i == j) return x[i]; 12 | 13 | if (dp[i][j] != -1) return dp[i][j]; 14 | 15 | // Choose either to remove the element at i or at j 16 | long long takeLeft = x[i] - maxScoreDifference(i + 1, j, x, dp); 17 | long long takeRight = x[j] - maxScoreDifference(i, j - 1, x, dp); 18 | 19 | // Store and return the maximum of these choices 20 | dp[i][j] = max(takeLeft, takeRight); 21 | return dp[i][j]; 22 | } 23 | 24 | int main() { 25 | 26 | cin >> n; 27 | vector x(n); 28 | for (int i = 0; i < n; ++i) { 29 | cin >> x[i]; 30 | } 31 | 32 | // Initialize DP table with -1 (indicating uncomputed states) 33 | vector> dp(n, vector(n, -1)); 34 | 35 | // Calculate the maximum score difference for the entire array 36 | long long total_sum = 0; 37 | for (int i = 0; i < n; ++i) { 38 | total_sum += x[i]; 39 | } 40 | long long max_score_difference = maxScoreDifference(0, n-1, x, dp); 41 | long long first_player_max_score = (total_sum + max_score_difference) / 2; 42 | 43 | cout << first_player_max_score << endl; 44 | 45 | return 0; 46 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1097_03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include // For memset 5 | 6 | using namespace std; 7 | 8 | const int MAXN = 5001; 9 | int n; 10 | long long x[MAXN]; 11 | long long dp[MAXN][MAXN]; 12 | 13 | // Recursive function with memoization to calculate the maximum score difference 14 | long long maxScoreDifference(int i, int j) { 15 | if (i > j) return 0; 16 | if (i == j) return x[i]; 17 | 18 | if (dp[i][j] != -1) return dp[i][j]; 19 | 20 | // Choose either to remove the element at i or at j 21 | long long takeLeft = x[i] - maxScoreDifference(i + 1, j); 22 | long long takeRight = x[j] - maxScoreDifference(i, j - 1); 23 | 24 | // Store and return the maximum of these choices 25 | dp[i][j] = max(takeLeft, takeRight); 26 | return dp[i][j]; 27 | } 28 | 29 | int main() { 30 | cin >> n; 31 | for (int i = 0; i < n; ++i) { 32 | cin >> x[i]; 33 | } 34 | 35 | // Initialize DP table with -1 (indicating uncomputed states) 36 | memset(dp, -1, sizeof(dp)); 37 | 38 | // Calculate the maximum score difference for the entire array 39 | long long total_sum = 0; 40 | for (int i = 0; i < n; ++i) { 41 | total_sum += x[i]; 42 | } 43 | long long max_score_difference = maxScoreDifference(0, n - 1); 44 | long long first_player_max_score = (total_sum + max_score_difference) / 2; 45 | 46 | cout << first_player_max_score << endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1145.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int lengthOfLIS(const vector& nums) { 8 | if (nums.empty()) return 0; 9 | 10 | vector tails; 11 | 12 | for (int num : nums) { 13 | auto it = lower_bound(tails.begin(), tails.end(), num); 14 | if (it == tails.end()) { 15 | tails.push_back(num); 16 | } else { 17 | *it = num; 18 | } 19 | } 20 | 21 | return tails.size(); 22 | } 23 | 24 | int main() { 25 | int n; 26 | cin >> n; 27 | vector nums(n); 28 | 29 | for (int i = 0; i < n; ++i) { 30 | cin >> nums[i]; 31 | } 32 | 33 | cout << lengthOfLIS(nums) << endl; 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1158.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | int n, x; 7 | 8 | int main() { 9 | 10 | cin >> n >> x; 11 | 12 | vector prices(n), pages(n); 13 | 14 | for (int i = 0; i < n; ++i) { 15 | cin >> prices[i]; 16 | } 17 | 18 | for (int i = 0; i < n; ++i) { 19 | cin >> pages[i]; 20 | } 21 | 22 | vector dp(x + 1, 0); // DP array to store the max pages for each budget 23 | 24 | for (int i = 0; i < n; ++i) { 25 | int price = prices[i]; 26 | int page = pages[i]; 27 | // Traverse dp array in reverse to prevent recomputation with the same book 28 | for (int j = x; j >= price; --j) { 29 | dp[j] = max(dp[j], dp[j - price] + page); 30 | } 31 | } 32 | 33 | cout << dp[x] << endl; 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1633.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int MOD = 1e9 + 7; 8 | const int MAXN = 10 + int(1e6); 9 | int n; 10 | int dp[MAXN]; 11 | 12 | int main() { 13 | 14 | cin >> n; 15 | 16 | memset(dp, 0, sizeof(dp)); 17 | dp[0] = 1; // Base case: there's one way to get the sum 0 18 | 19 | for (int i = 1; i <= n; ++i) { 20 | for (int j = 1; j <= 6; ++j) { 21 | if (i - j >= 0) { 22 | dp[i] = (dp[i] + dp[i - j]) % MOD; 23 | } 24 | } 25 | } 26 | 27 | cout << dp[n] << endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1634.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int INF = 1e9; // A large number representing infinity 8 | 9 | int main() { 10 | int n, x; 11 | cin >> n >> x; 12 | 13 | vector coins(n); 14 | for (int i = 0; i < n; ++i) { 15 | cin >> coins[i]; 16 | } 17 | 18 | vector dp(x + 1, INF); 19 | dp[0] = 0; // Base case: no coins are needed to make the sum 0 20 | 21 | for (int coin : coins) { 22 | for (int j = coin; j <= x; ++j) { 23 | if (dp[j - coin] != INF) { 24 | dp[j] = min(dp[j], dp[j - coin] + 1); 25 | } 26 | } 27 | } 28 | 29 | if (dp[x] == INF) { 30 | cout << -1 << endl; 31 | } else { 32 | cout << dp[x] << endl; 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1635.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | int main() { 9 | int n, x; 10 | cin >> n >> x; 11 | 12 | vector coins(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> coins[i]; 15 | } 16 | 17 | vector dp(x + 1, 0); 18 | dp[0] = 1; // Base case: there's one way to get the sum 0 19 | 20 | for (int coin : coins) { 21 | for (int i = coin; i <= x; ++i) { 22 | dp[i] = (dp[i] + dp[i - coin]) % MOD; 23 | } 24 | } 25 | 26 | cout << dp[x] << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1636.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | int main() { 9 | int n, x; 10 | cin >> n >> x; 11 | 12 | vector coins(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> coins[i]; 15 | } 16 | 17 | vector dp(x + 1, 0); 18 | dp[0] = 1; // Base case: there's one way to get the sum 0 19 | 20 | for (int coin : coins) { 21 | for (int i = coin; i <= x; ++i) { 22 | dp[i] = (dp[i] + dp[i - coin]) % MOD; 23 | } 24 | } 25 | 26 | cout << dp[x] << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1637.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int minStepsToZero(int n) { 9 | queue> q; 10 | unordered_set visited; 11 | 12 | q.push({n, 0}); 13 | visited.insert(n); 14 | 15 | while (!q.empty()) { 16 | auto [current, steps] = q.front(); 17 | q.pop(); 18 | 19 | if (current == 0) { 20 | return steps; 21 | } 22 | 23 | string numStr = to_string(current); 24 | for (char digitChar : numStr) { 25 | int digit = digitChar - '0'; 26 | int next = current - digit; 27 | 28 | if (next >= 0 && visited.find(next) == visited.end()) { 29 | q.push({next, steps + 1}); 30 | visited.insert(next); 31 | } 32 | } 33 | } 34 | 35 | return -1; // This should never happen for valid inputs 36 | } 37 | 38 | int main() { 39 | int n; 40 | cin >> n; 41 | cout << minStepsToZero(n) << endl; 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1637_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | int n; 10 | cin >> n; 11 | 12 | vector dp(n + 1, INT_MAX); 13 | dp[0] = 0; 14 | 15 | for (int i = 1; i <= n; ++i) { 16 | int current = i; 17 | while (current > 0) { 18 | int digit = current % 10; 19 | if (digit > 0) { 20 | dp[i] = min(dp[i], dp[i - digit] + 1); 21 | } 22 | current /= 10; 23 | } 24 | } 25 | 26 | cout << dp[n] << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1638.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | int main() { 9 | int n; 10 | cin >> n; 11 | 12 | vector> grid(n, vector(n)); 13 | vector> dp(n, vector(n, 0)); 14 | 15 | // Read the grid 16 | for (int i = 0; i < n; ++i) { 17 | for (int j = 0; j < n; ++j) { 18 | cin >> grid[i][j]; 19 | } 20 | } 21 | 22 | // Initialize dp 23 | if (grid[0][0] == '.') { 24 | dp[0][0] = 1; 25 | } 26 | 27 | // Fill dp table 28 | for (int i = 0; i < n; ++i) { 29 | for (int j = 0; j < n; ++j) { 30 | if (grid[i][j] == '*') { 31 | dp[i][j] = 0; 32 | } else { 33 | if (i > 0) { 34 | dp[i][j] = (dp[i][j] + dp[i-1][j]) % MOD; 35 | } 36 | if (j > 0) { 37 | dp[i][j] = (dp[i][j] + dp[i][j-1]) % MOD; 38 | } 39 | } 40 | } 41 | } 42 | 43 | cout << dp[n-1][n-1] << endl; 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1639.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int editDistance(const string& s1, const string& s2) { 9 | int n = s1.length(); 10 | int m = s2.length(); 11 | vector> dp(n + 1, vector(m + 1)); 12 | 13 | // Initialize the base cases 14 | for (int i = 0; i <= n; ++i) { 15 | dp[i][0] = i; // Cost of deleting all characters from s1 16 | } 17 | for (int j = 0; j <= m; ++j) { 18 | dp[0][j] = j; // Cost of inserting all characters into s1 19 | } 20 | 21 | // Fill the dp table 22 | for (int i = 1; i <= n; ++i) { 23 | for (int j = 1; j <= m; ++j) { 24 | if (s1[i - 1] == s2[j - 1]) { 25 | dp[i][j] = dp[i - 1][j - 1]; // No change needed 26 | } else { 27 | dp[i][j] = min({ 28 | dp[i - 1][j] + 1, // Delete 29 | dp[i][j - 1] + 1, // Insert 30 | dp[i - 1][j - 1] + 1 // Replace 31 | }); 32 | } 33 | } 34 | } 35 | 36 | return dp[n][m]; 37 | } 38 | 39 | int main() { 40 | string s1, s2; 41 | cin >> s1 >> s2; 42 | cout << editDistance(s1, s2) << endl; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1744.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int INF = 1e9; 8 | 9 | int main() { 10 | int a, b; 11 | cin >> a >> b; 12 | 13 | // Initialize the dp table 14 | vector> dp(a + 1, vector(b + 1, INF)); 15 | 16 | // Fill the dp table 17 | for (int i = 1; i <= a; ++i) { 18 | for (int j = 1; j <= b; ++j) { 19 | if (i == j) { 20 | dp[i][j] = 0; // No moves needed if it's already a square 21 | } else { 22 | // Vertical cuts 23 | for (int k = 1; k < i; ++k) { 24 | dp[i][j] = min(dp[i][j], 1 + dp[k][j] + dp[i - k][j]); 25 | } 26 | // Horizontal cuts 27 | for (int k = 1; k < j; ++k) { 28 | dp[i][j] = min(dp[i][j], 1 + dp[i][k] + dp[i][j - k]); 29 | } 30 | } 31 | } 32 | } 33 | 34 | cout << dp[a][b] << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1745.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | int n; 10 | cin >> n; 11 | 12 | vector coins(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> coins[i]; 15 | } 16 | 17 | set possible_sums; 18 | possible_sums.insert(0); 19 | 20 | for (int coin : coins) { 21 | vector new_sums; 22 | for (int sum : possible_sums) { 23 | new_sums.push_back(sum + coin); 24 | } 25 | for (int new_sum : new_sums) { 26 | possible_sums.insert(new_sum); 27 | } 28 | } 29 | 30 | // Remove 0 if it is not required in the output 31 | possible_sums.erase(0); 32 | 33 | vector sorted_sums(possible_sums.begin(), possible_sums.end()); 34 | 35 | cout << sorted_sums.size() << endl; 36 | for (int sum : sorted_sums) { 37 | cout << sum << " "; 38 | } 39 | cout << endl; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /dynamic-programming/cses_1746.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | int main() { 9 | int n, m; 10 | cin >> n >> m; 11 | 12 | vector x(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> x[i]; 15 | } 16 | 17 | vector> dp(n, vector(m + 1, 0)); 18 | 19 | // Initialization for the first index 20 | if (x[0] == 0) { 21 | for (int v = 1; v <= m; ++v) { 22 | dp[0][v] = 1; 23 | } 24 | } else { 25 | dp[0][x[0]] = 1; 26 | } 27 | 28 | // Fill the dp table 29 | for (int i = 1; i < n; ++i) { 30 | if (x[i] == 0) { 31 | for (int v = 1; v <= m; ++v) { 32 | dp[i][v] = dp[i-1][v]; 33 | if (v > 1) dp[i][v] = (dp[i][v] + dp[i-1][v-1]) % MOD; 34 | if (v < m) dp[i][v] = (dp[i][v] + dp[i-1][v+1]) % MOD; 35 | } 36 | } else { 37 | int v = x[i]; 38 | dp[i][v] = dp[i-1][v]; 39 | if (v > 1) dp[i][v] = (dp[i][v] + dp[i-1][v-1]) % MOD; 40 | if (v < m) dp[i][v] = (dp[i][v] + dp[i-1][v+1]) % MOD; 41 | } 42 | } 43 | 44 | int result = 0; 45 | for (int v = 1; v <= m; ++v) { 46 | result = (result + dp[n-1][v]) % MOD; 47 | } 48 | 49 | cout << result << endl; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /dynamic-programming/cses_2181.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | int main() { 9 | int n, m; 10 | cin >> n >> m; 11 | 12 | vector> dp(n + 1, vector(m + 1, 0)); 13 | dp[0][0] = 1; 14 | 15 | for (int i = 0; i <= n; ++i) { 16 | for (int j = 0; j <= m; ++j) { 17 | if (dp[i][j] > 0) { 18 | if (i + 1 <= n && j + 1 <= m) { 19 | dp[i + 1][j + 1] = (dp[i + 1][j + 1] + dp[i][j]) % MOD; 20 | } 21 | if (i + 2 <= n) { 22 | dp[i + 2][j] = (dp[i + 2][j] + dp[i][j]) % MOD; 23 | } 24 | if (j + 2 <= m) { 25 | dp[i][j + 2] = (dp[i][j + 2] + dp[i][j]) % MOD; 26 | } 27 | } 28 | } 29 | } 30 | 31 | cout << dp[n][m] << endl; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /dynamic-programming/cses_2220.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector digits; 8 | long long dp[20][11][2][2]; // Adding another dimension to track if the number has started (no leading zeros) 9 | 10 | // Recursive DP function 11 | long long digit_dp(int pos, int prev_digit, bool tight, bool num_started) { 12 | if (pos == digits.size()) { 13 | return 1; // Valid number found 14 | } 15 | 16 | if (dp[pos][prev_digit][tight][num_started] != -1) { 17 | return dp[pos][prev_digit][tight][num_started]; 18 | } 19 | 20 | int limit = tight ? digits[pos] : 9; 21 | long long res = 0; 22 | 23 | for (int d = 0; d <= limit; ++d) { 24 | if (!num_started || d != prev_digit) { // Ensure no two consecutive digits are the same unless it's leading zeros 25 | res += digit_dp(pos + 1, d, tight && (d == limit), num_started || d != 0); 26 | } 27 | } 28 | 29 | return dp[pos][prev_digit][tight][num_started] = res; 30 | } 31 | 32 | // Helper function to count valid numbers <= n 33 | long long count_valid(long long n) { 34 | if (n < 0) return 0; // Edge case when n is 0 35 | if (n == 0) return 1; // Special case for 0 36 | 37 | digits.clear(); 38 | while (n > 0) { 39 | digits.push_back(n % 10); 40 | n /= 10; 41 | } 42 | reverse(digits.begin(), digits.end()); 43 | 44 | memset(dp, -1, sizeof(dp)); 45 | 46 | return digit_dp(0, 10, 1, 0); // Start with prev_digit = 10 (no prev digit), tight=true, and num_started=false 47 | } 48 | 49 | // Main function to solve the range problem 50 | int main() { 51 | long long a, b; 52 | 53 | cin >> a >> b; 54 | 55 | long long result_b = count_valid(b); // Count valid numbers <= b 56 | long long result_a = count_valid(a - 1); // Count valid numbers < a 57 | 58 | cout << result_b - result_a << endl; // Difference gives valid numbers in range [a, b] 59 | 60 | return 0; 61 | } 62 | 63 | // g++ -std=c++11 dp_digitC.cpp -o a && ./a < a.in 64 | -------------------------------------------------------------------------------- /dynamic-programming/cses_2413.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | const int MAX_N = 1000000; 8 | 9 | vector dp(MAX_N + 1, 0); 10 | 11 | void compute_dp() { 12 | dp[0] = 1; 13 | for (int i = 1; i <= MAX_N; ++i) { 14 | dp[i] = (dp[i-1] * 3) % MOD; 15 | if (i >= 2) { 16 | dp[i] = (dp[i] + dp[i-2] * 2) % MOD; 17 | } 18 | } 19 | } 20 | 21 | int main() { 22 | ios::sync_with_stdio(false); 23 | cin.tie(nullptr); 24 | 25 | int t; 26 | cin >> t; 27 | 28 | vector queries(t); 29 | int max_n = 0; 30 | for (int i = 0; i < t; ++i) { 31 | cin >> queries[i]; 32 | if (queries[i] > max_n) { 33 | max_n = queries[i]; 34 | } 35 | } 36 | 37 | // Compute dp values up to the maximum `n` in queries 38 | compute_dp(); 39 | 40 | // Output results for each query 41 | for (int i = 0; i < t; ++i) { 42 | cout << dp[queries[i]] << endl; 43 | } 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /dynamic-programming/digit_cf_628.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef long long ll; 8 | 9 | // Function to calculate the product of digits of a number 10 | ll digit_product(ll n) { 11 | ll product = 1; 12 | while (n > 0) { 13 | ll digit = n % 10; 14 | if (digit == 0) return 0; // If any digit is 0, the product will be 0 15 | product *= digit; 16 | n /= 10; 17 | } 18 | return product; 19 | } 20 | 21 | // Function to get the number with maximum digit product in range [a, b] 22 | ll find_max_digit_product(ll a, ll b) { 23 | ll max_product = digit_product(a); 24 | ll result = a; 25 | 26 | // Check all candidate numbers near b by changing digits to 9 27 | string s_b = to_string(b); 28 | int n = s_b.size(); 29 | 30 | // Check the number b itself 31 | ll b_product = digit_product(b); 32 | if (b_product > max_product) { 33 | max_product = b_product; 34 | result = b; 35 | } 36 | 37 | // Try to create numbers by setting some digits to 9 from b 38 | for (int i = 0; i < n; ++i) { 39 | if (s_b[i] == '0') continue; // Skip if the digit is already 0 40 | 41 | // Create a number by decreasing the current digit and setting subsequent digits to 9 42 | string temp = s_b; 43 | temp[i]--; // Decrease the current digit 44 | for (int j = i + 1; j < n; ++j) { 45 | temp[j] = '9'; // Set all digits after to 9 46 | } 47 | 48 | ll candidate = stoll(temp); 49 | if (candidate >= a) { 50 | ll candidate_product = digit_product(candidate); 51 | if (candidate_product > max_product) { 52 | max_product = candidate_product; 53 | result = candidate; 54 | } 55 | } 56 | } 57 | 58 | return result; 59 | } 60 | 61 | int main() { 62 | ll a, b; 63 | cin >> a >> b; 64 | 65 | ll result = find_max_digit_product(a, b); 66 | cout << result << endl; 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /dynamic-programming/number_13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef long long ll; 8 | 9 | vector digits; 10 | ll dp[20][2][2][2]; // dp[pos][last1][contains_13][tight]: pos -> current digit, last1 -> if last digit was 1, contains_13 -> whether we've already seen "13", tight -> if we are bound by the number `n` 11 | 12 | // Function to calculate how many numbers do not contain "13" 13 | ll digit_dp(int pos, bool last1, bool contains_13, bool tight) { 14 | if (contains_13) return 0; // If "13" has already been found, exclude this number 15 | if (pos == digits.size()) return 1; // Valid number, so return 1 16 | if (dp[pos][last1][contains_13][tight] != -1) return dp[pos][last1][contains_13][tight]; 17 | 18 | ll ans = 0; 19 | int limit = tight ? digits[pos] : 9; // If tight, limit this position to the corresponding digit of n 20 | 21 | for (int d = 0; d <= limit; ++d) { 22 | ans += digit_dp(pos + 1, d == 1, last1 && d == 3, tight && (d == limit)); 23 | } 24 | 25 | return dp[pos][last1][contains_13][tight] = ans; 26 | } 27 | 28 | // Function to count how many numbers from 0 to n do not contain "13" 29 | ll count_numbers_without_13(ll n) { 30 | if (n < 0) return 0; 31 | 32 | digits.clear(); 33 | while (n > 0) { 34 | digits.push_back(n % 10); // Extract digits 35 | n /= 10; 36 | } 37 | 38 | reverse(digits.begin(), digits.end()); // Reverse to process from the most significant digit 39 | memset(dp, -1, sizeof(dp)); // Reset the dp table 40 | 41 | return digit_dp(0, false, false, true); 42 | } 43 | 44 | int main() { 45 | ll l, r; 46 | cin >> l >> r; 47 | 48 | // Count numbers without "13" from l to r 49 | ll result = count_numbers_without_13(r) - count_numbers_without_13(l - 1); 50 | 51 | cout << result << endl; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /dynamic-programming/spoj_PR003004.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef long long ll; 8 | 9 | vector digits; 10 | ll dp[20][180][2]; // dp[pos][sum][tight]: pos -> current digit position, sum -> sum of digits till now, tight -> if we're bound by the number `n` 11 | 12 | // Digit DP function to calculate sum of digits from 0 to n 13 | ll digit_sum_dp(int pos, int sum, bool tight) { 14 | if (pos == digits.size()) return sum; // Base case: when we've processed all digits, return the sum 15 | if (dp[pos][sum][tight] != -1) return dp[pos][sum][tight]; 16 | 17 | ll ans = 0; 18 | int limit = tight ? digits[pos] : 9; // If tight is true, we must limit this position to the corresponding digit of n 19 | 20 | for (int d = 0; d <= limit; ++d) { 21 | ans += digit_sum_dp(pos + 1, sum + d, tight && (d == limit)); // Proceed with the next digit 22 | } 23 | 24 | return dp[pos][sum][tight] = ans; 25 | } 26 | 27 | // Function to compute digit sum for all numbers from 0 to n 28 | ll digit_sum(ll n) { 29 | if (n < 0) return 0; 30 | 31 | digits.clear(); 32 | while (n > 0) { 33 | digits.push_back(n % 10); // Extract digits 34 | n /= 10; 35 | } 36 | 37 | reverse(digits.begin(), digits.end()); // Reverse to process from the most significant digit 38 | memset(dp, -1, sizeof(dp)); // Reset the dp table 39 | 40 | return digit_sum_dp(0, 0, true); 41 | } 42 | 43 | int main() { 44 | int t; 45 | cin >> t; // Number of test cases 46 | while (t--) { 47 | ll a, b; 48 | cin >> a >> b; 49 | 50 | // Calculate the digit sum in the range [a, b] 51 | ll result = digit_sum(b) - digit_sum(a - 1); 52 | cout << result << endl; 53 | } 54 | 55 | return 0; 56 | } 57 | 58 | // g++ -std=c++11 -O2 -Wall spoj_PR003004.cpp -o a && ./a -------------------------------------------------------------------------------- /graph-theory/cs-matrix.cpp: -------------------------------------------------------------------------------- 1 | // find fibonaci number N using matrix exponentiation 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MOD = 1e9 + 7; 7 | int base[2][2]; 8 | int result[2][2]; 9 | 10 | void multiply(int a[2][2], int b[2][2]) { 11 | int res[2][2]; 12 | for (int i = 0; i < 2; i++) { 13 | for (int j = 0; j < 2; j++) { 14 | res[i][j] = 0; 15 | for (int k = 0; k < 2; k++) { 16 | res[i][j] = (res[i][j] + 1LL * a[i][k] * b[k][j]) % MOD; 17 | } 18 | } 19 | } 20 | for (int i = 0; i < 2; i++) { 21 | for (int j = 0; j < 2; j++) { 22 | a[i][j] = res[i][j]; 23 | } 24 | } 25 | } 26 | 27 | void power(long long n) { 28 | result[0][0] = 0; result[0][1] = 1; 29 | 30 | while (n > 0) { 31 | if (n & 1) { 32 | multiply(result, base); 33 | } 34 | multiply(base, base); 35 | n >>= 1; 36 | } 37 | 38 | } 39 | 40 | int main() { 41 | long long n; 42 | cin >> n; 43 | if (n <= 1) { 44 | cout << n << endl; 45 | return 0; 46 | } 47 | 48 | base[0][0] = 0; 49 | base[0][1] = base[1][0] = base[1][1] = 1; 50 | 51 | power(n); 52 | cout << result[0][0] << endl; 53 | 54 | return 0; 55 | } 56 | 57 | // g++ -std=c++11 -O2 -Wall cs-matrix.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_1130.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | vector> tree; 7 | vector visited; 8 | int max_matching = 0; 9 | 10 | void dfs(int node, int parent) { 11 | for (int neighbor : tree[node]) { 12 | if (neighbor == parent) continue; 13 | dfs(neighbor, node); 14 | if (!visited[neighbor] && !visited[node]) { 15 | max_matching++; 16 | visited[neighbor] = true; 17 | visited[node] = true; 18 | } 19 | } 20 | 21 | } 22 | 23 | int main() { 24 | int n; 25 | cin >> n; 26 | 27 | tree.resize(n + 1); 28 | visited.resize(n + 1, false); 29 | 30 | for (int i = 0; i < n - 1; i++) { 31 | int a, b; 32 | cin >> a >> b; 33 | tree[a].push_back(b); 34 | tree[b].push_back(a); 35 | } 36 | 37 | // Start DFS from the root node (1) 38 | dfs(1, -1); 39 | 40 | // Output the maximum matching found 41 | cout << max_matching << endl; 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /graph-theory/cses_1131.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector> tree; 8 | vector visited; 9 | 10 | pair dfs(int node) { 11 | visited[node] = true; 12 | pair farthest = {0, node}; // {distance, node} 13 | 14 | for (int neighbor : tree[node]) { 15 | if (!visited[neighbor]) { 16 | pair dist = dfs(neighbor); 17 | dist.first += 1; // Increase distance by 1 for the current edge 18 | if (dist.first > farthest.first) { 19 | farthest = dist; 20 | } 21 | } 22 | } 23 | 24 | return farthest; 25 | } 26 | 27 | int main() { 28 | int n; 29 | cin >> n; 30 | 31 | tree.resize(n + 1); 32 | visited.resize(n + 1, false); 33 | 34 | // Reading edges 35 | for (int i = 0; i < n - 1; i++) { 36 | int a, b; 37 | cin >> a >> b; 38 | tree[a].push_back(b); 39 | tree[b].push_back(a); 40 | } 41 | 42 | // First DFS to find the farthest node from an arbitrary node (let's use node 1) 43 | pair first = dfs(1); 44 | 45 | // Reset visited array 46 | fill(visited.begin(), visited.end(), false); 47 | 48 | // Second DFS from the farthest node found to determine the diameter 49 | pair second = dfs(first.second); 50 | 51 | // Output the diameter of the tree 52 | cout << second.first << endl; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /graph-theory/cses_1132.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector> tree; 8 | vector dist_from_A; 9 | vector dist_from_B; 10 | 11 | void dfs(int node, int parent, vector& dist) { 12 | for (int neighbor : tree[node]) { 13 | if (neighbor != parent) { 14 | dist[neighbor] = dist[node] + 1; 15 | dfs(neighbor, node, dist); 16 | } 17 | } 18 | } 19 | 20 | int main() { 21 | int n; 22 | cin >> n; 23 | 24 | tree.resize(n + 1); 25 | dist_from_A.resize(n + 1, 0); 26 | dist_from_B.resize(n + 1, 0); 27 | 28 | // Reading edges 29 | for (int i = 0; i < n - 1; i++) { 30 | int a, b; 31 | cin >> a >> b; 32 | tree[a].push_back(b); 33 | tree[b].push_back(a); 34 | } 35 | 36 | // First DFS to find the farthest node from an arbitrary node (let's use node 1) 37 | dfs(1, -1, dist_from_A); 38 | int A = max_element(dist_from_A.begin(), dist_from_A.end()) - dist_from_A.begin(); 39 | 40 | // Second DFS from the farthest node A to find the farthest node B 41 | fill(dist_from_A.begin(), dist_from_A.end(), 0); 42 | dfs(A, -1, dist_from_A); 43 | int B = max_element(dist_from_A.begin(), dist_from_A.end()) - dist_from_A.begin(); 44 | 45 | // Third DFS from node B to get distances from B 46 | dfs(B, -1, dist_from_B); 47 | 48 | // Output the maximum of distances from A and B for each node 49 | for (int i = 1; i <= n; i++) { 50 | cout << max(dist_from_A[i], dist_from_B[i]) << " "; 51 | } 52 | cout << endl; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /graph-theory/cses_1133.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | vector> tree; 7 | vector subtree_size; 8 | vector distance_sum; 9 | 10 | void dfs1(int node, int parent) { 11 | subtree_size[node] = 1; // Start with size 1 for the node itself 12 | distance_sum[node] = 0; 13 | 14 | for (int neighbor : tree[node]) { 15 | if (neighbor == parent) continue; 16 | dfs1(neighbor, node); 17 | subtree_size[node] += subtree_size[neighbor]; 18 | distance_sum[node] += distance_sum[neighbor] + subtree_size[neighbor]; 19 | } 20 | } 21 | 22 | void dfs2(int node, int parent, int n) { 23 | for (int neighbor : tree[node]) { 24 | if (neighbor == parent) continue; 25 | // Recalculate the distance sum for the child node 26 | distance_sum[neighbor] = distance_sum[node] + (n - subtree_size[neighbor]) - subtree_size[neighbor]; 27 | dfs2(neighbor, node, n); 28 | } 29 | } 30 | 31 | int main() { 32 | int n; 33 | cin >> n; 34 | 35 | tree.resize(n + 1); 36 | subtree_size.resize(n + 1); 37 | distance_sum.resize(n + 1); 38 | 39 | // Reading edges 40 | for (int i = 0; i < n - 1; i++) { 41 | int a, b; 42 | cin >> a >> b; 43 | tree[a].push_back(b); 44 | tree[b].push_back(a); 45 | } 46 | 47 | // Initial DFS to calculate subtree sizes and sum of distances for root node (1) 48 | dfs1(1, -1); 49 | 50 | // Second DFS to propagate the sum of distances from the root to all nodes 51 | dfs2(1, -1, n); 52 | 53 | // Output the sum of distances for each node 54 | for (int i = 1; i <= n; i++) { 55 | cout << distance_sum[i] << " "; 56 | } 57 | cout << endl; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /graph-theory/cses_1135.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int LOG = 18; // log2(200000) ~ 17.6, so we use 18 for safety 7 | 8 | vector> up; 9 | vector depth; 10 | 11 | void dfs(int node, int parent, const vector>& adj) { 12 | up[node][0] = parent; 13 | for (int i = 1; i <= LOG; ++i) { 14 | if (up[node][i - 1] != -1) { 15 | up[node][i] = up[up[node][i - 1]][i - 1]; 16 | } 17 | } 18 | for (int neighbor : adj[node]) { 19 | if (neighbor != parent) { 20 | depth[neighbor] = depth[node] + 1; 21 | dfs(neighbor, node, adj); 22 | } 23 | } 24 | } 25 | 26 | int lca(int a, int b) { 27 | if (depth[a] < depth[b]) swap(a, b); 28 | 29 | // Bring a and b to the same depth 30 | for (int i = LOG; i >= 0; --i) { 31 | if (depth[a] - (1 << i) >= depth[b]) { 32 | a = up[a][i]; 33 | } 34 | } 35 | 36 | if (a == b) return a; 37 | 38 | // Lift both a and b up until they meet at LCA 39 | for (int i = LOG; i >= 0; --i) { 40 | if (up[a][i] != up[b][i]) { 41 | a = up[a][i]; 42 | b = up[b][i]; 43 | } 44 | } 45 | 46 | return up[a][0]; 47 | } 48 | 49 | int main() { 50 | ios::sync_with_stdio(0); 51 | cin.tie(0); 52 | int n, q; 53 | cin >> n >> q; 54 | 55 | vector> adj(n + 1); 56 | up.assign(n + 1, vector(LOG + 1, -1)); 57 | depth.assign(n + 1, 0); 58 | 59 | for (int i = 0; i < n - 1; ++i) { 60 | int a, b; 61 | cin >> a >> b; 62 | adj[a].push_back(b); 63 | adj[b].push_back(a); 64 | } 65 | 66 | // Start DFS from node 1 (assuming it's the root) 67 | dfs(1, -1, adj); 68 | 69 | for (int i = 0; i < q; ++i) { 70 | int a, b; 71 | cin >> a >> b; 72 | int lca_ab = lca(a, b); 73 | int distance = depth[a] + depth[b] - 2 * depth[lca_ab]; 74 | cout << distance << endl; 75 | } 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /graph-theory/cses_1139.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int MAXN = 200005; 9 | 10 | vector adj[MAXN]; 11 | int color[MAXN]; 12 | int result[MAXN]; 13 | 14 | void dfs(int node, int parent, vector>& color_sets) { 15 | color_sets[node].insert(color[node]); 16 | 17 | for (int child : adj[node]) { 18 | if (child == parent) continue; 19 | 20 | dfs(child, node, color_sets); 21 | 22 | // Always merge the smaller set into the larger set 23 | if (color_sets[child].size() > color_sets[node].size()) { 24 | swap(color_sets[child], color_sets[node]); 25 | } 26 | 27 | for (int c : color_sets[child]) { 28 | color_sets[node].insert(c); 29 | } 30 | color_sets[child].clear(); // Clear the child set to save memory 31 | } 32 | 33 | result[node] = color_sets[node].size(); 34 | } 35 | 36 | int main() { 37 | ios::sync_with_stdio(false); 38 | cin.tie(0); 39 | 40 | int n; 41 | cin >> n; 42 | 43 | for (int i = 1; i <= n; i++) { 44 | cin >> color[i]; 45 | } 46 | 47 | for (int i = 0; i < n - 1; i++) { 48 | int a, b; 49 | cin >> a >> b; 50 | adj[a].push_back(b); 51 | adj[b].push_back(a); 52 | } 53 | 54 | vector> color_sets(n + 1); 55 | 56 | dfs(1, -1, color_sets); 57 | 58 | for (int i = 1; i <= n; i++) { 59 | cout << result[i] << " "; 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /graph-theory/cses_1192.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void dfs(int x, int y, const vector>& map, vector>& visited) { 8 | int n = map.size(); 9 | int m = map[0].size(); 10 | stack> s; 11 | s.push({x, y}); 12 | visited[x][y] = true; 13 | 14 | int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // Right, Down, Left, Up 15 | 16 | while (!s.empty()) { 17 | int cx = s.top().first; 18 | int cy = s.top().second; 19 | s.pop(); 20 | 21 | for (int i = 0; i < 4; ++i) { 22 | int nx = cx + directions[i][0]; 23 | int ny = cy + directions[i][1]; 24 | 25 | if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny] && map[nx][ny] == '.') { 26 | visited[nx][ny] = true; 27 | s.push({nx, ny}); 28 | } 29 | } 30 | } 31 | } 32 | 33 | int main() { 34 | int n, m; 35 | cin >> n >> m; 36 | 37 | vector> map(n, vector(m)); 38 | vector> visited(n, vector(m, false)); 39 | 40 | for (int i = 0; i < n; ++i) { 41 | for (int j = 0; j < m; ++j) { 42 | cin >> map[i][j]; 43 | } 44 | } 45 | 46 | int room_count = 0; 47 | 48 | for (int i = 0; i < n; ++i) { 49 | for (int j = 0; j < m; ++j) { 50 | if (map[i][j] == '.' && !visited[i][j]) { 51 | ++room_count; 52 | dfs(i, j, map, visited); 53 | } 54 | } 55 | } 56 | 57 | cout << room_count << endl; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /graph-theory/cses_1196.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef long long ll; 9 | typedef pair pli; 10 | 11 | // const ll INF = 1e18; 12 | 13 | int main() { 14 | // https://en.wikipedia.org/wiki/K_shortest_path_routing 15 | int n, m, k; 16 | cin >> n >> m >> k; 17 | 18 | vector> adj(n + 1); // adjacency list with pairs (cost, destination) 19 | for (int i = 0; i < m; i++) { 20 | int a, b; 21 | ll c; 22 | cin >> a >> b >> c; 23 | adj[a].emplace_back(c, b); 24 | } 25 | 26 | // Min-heap priority queue (cost, node) 27 | priority_queue, greater> pq; 28 | vector> dist(n + 1); // dist[i] stores the k shortest distances to node i 29 | 30 | pq.push({0, 1}); // start from city 1 with cost 0 31 | 32 | while (!pq.empty()) { 33 | ll cost = pq.top().first; 34 | int u = pq.top().second; 35 | pq.pop(); 36 | 37 | // If we've already found k paths to this city, continue 38 | if ((int)dist[u].size() >= k) continue; 39 | 40 | dist[u].push_back(cost); 41 | 42 | // Explore neighbors 43 | for (auto &[nextCost, v] : adj[u]) { 44 | ll newCost = cost + nextCost; 45 | if (dist[v].size() < k) { 46 | pq.push({newCost, v}); 47 | } 48 | } 49 | } 50 | 51 | // Output the k shortest paths to node n 52 | for (ll d : dist[n]) { 53 | cout << d << " "; 54 | } 55 | cout << endl; 56 | 57 | return 0; 58 | } 59 | // g++ -std=c++17 -O2 -Wall cses_1196.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_1197.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | const long long INF = 1LL<<62; 10 | 11 | int main() { 12 | int n, m; 13 | cin >> n >> m; 14 | 15 | vector> edges; 16 | vector distance(n + 1, INF); 17 | vector predecessor(n + 1, -1); 18 | 19 | for (int i = 0; i < m; ++i) { 20 | int a, b; 21 | long long c; 22 | cin >> a >> b >> c; 23 | edges.push_back({a, b, c}); 24 | } 25 | 26 | // distance[1] = 0; 27 | int x = -1; 28 | 29 | for (int i = 0; i < n; ++i) { 30 | x = -1; 31 | for (const auto& [a, b, c] : edges) { 32 | // if (distance[a] != INF && distance[a] + c < distance[b]) { 33 | if (distance[a] + c < distance[b]) { 34 | distance[b] = distance[a] + c; 35 | predecessor[b] = a; 36 | x = b; 37 | } 38 | } 39 | } 40 | 41 | if (x == -1) { 42 | cout << "NO" << endl; 43 | } else { 44 | // There is a negative cycle, now find the cycle 45 | for (int i = 0; i < n; ++i) { 46 | x = predecessor[x]; 47 | } 48 | 49 | vector cycle; 50 | for (int v = x; ; v = predecessor[v]) { 51 | cycle.push_back(v); 52 | if (v == x && cycle.size() > 1) break; 53 | } 54 | 55 | reverse(cycle.begin(), cycle.end()); 56 | 57 | cout << "YES" << endl; 58 | for (int v : cycle) { 59 | cout << v << " "; 60 | } 61 | cout << endl; 62 | } 63 | // cout << INF << " " << LLONG_MAX << " " << LLONG_MAX + 1 << endl; 64 | return 0; 65 | } 66 | // g++ -std=c++20 -o a cses_1197.cpp && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_1202.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const long long INF = 1e18; 9 | const int MOD = 1e9 + 7; 10 | 11 | struct Edge { 12 | int to; 13 | long long cost; 14 | }; 15 | 16 | int main() { 17 | int n, m; 18 | cin >> n >> m; 19 | 20 | vector> adj(n + 1); 21 | for (int i = 0; i < m; i++) { 22 | int a, b; 23 | long long c; 24 | cin >> a >> b >> c; 25 | adj[a].push_back({b, c}); 26 | } 27 | 28 | vector dist(n + 1, INF); 29 | vector ways(n + 1, 0); 30 | vector min_flights(n + 1, INT_MAX); 31 | vector max_flights(n + 1, 0); 32 | 33 | priority_queue, vector>, greater<>> pq; 34 | dist[1] = 0; 35 | ways[1] = 1; 36 | min_flights[1] = 0; 37 | max_flights[1] = 0; 38 | pq.push({0, 1}); 39 | 40 | while (!pq.empty()) { 41 | auto [d, u] = pq.top(); pq.pop(); 42 | if (d != dist[u]) continue; 43 | 44 | for (auto& edge : adj[u]) { 45 | int v = edge.to; 46 | long long new_dist = d + edge.cost; 47 | 48 | if (new_dist < dist[v]) { 49 | dist[v] = new_dist; 50 | ways[v] = ways[u]; 51 | min_flights[v] = min_flights[u] + 1; 52 | max_flights[v] = max_flights[u] + 1; 53 | pq.push({new_dist, v}); 54 | } else if (new_dist == dist[v]) { 55 | ways[v] = (ways[v] + ways[u]) % MOD; 56 | min_flights[v] = min(min_flights[v], min_flights[u] + 1); 57 | max_flights[v] = max(max_flights[v], max_flights[u] + 1); 58 | } 59 | } 60 | } 61 | 62 | cout << dist[n] << " " << ways[n] << " " << min_flights[n] << " " << max_flights[n] << endl; 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /graph-theory/cses_1666.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void bfs(int start, const vector>& adj, vector& visited) { 8 | queue q; 9 | q.push(start); 10 | visited[start] = true; 11 | 12 | while (!q.empty()) { 13 | int node = q.front(); 14 | q.pop(); 15 | for (int neighbor : adj[node]) { 16 | if (!visited[neighbor]) { 17 | visited[neighbor] = true; 18 | q.push(neighbor); 19 | } 20 | } 21 | } 22 | } 23 | 24 | int main() { 25 | int n, m; 26 | cin >> n >> m; 27 | 28 | vector> adj(n + 1); 29 | vector visited(n + 1, false); 30 | 31 | for (int i = 0; i < m; ++i) { 32 | int a, b; 33 | cin >> a >> b; 34 | adj[a].push_back(b); 35 | adj[b].push_back(a); 36 | } 37 | 38 | vector component_representatives; 39 | 40 | for (int i = 1; i <= n; ++i) { 41 | if (!visited[i]) { 42 | component_representatives.push_back(i); 43 | bfs(i, adj, visited); 44 | } 45 | } 46 | 47 | int num_new_roads = component_representatives.size() - 1; 48 | cout << num_new_roads << endl; 49 | 50 | for (int i = 1; i < component_representatives.size(); ++i) { 51 | cout << component_representatives[i - 1] << " " << component_representatives[i] << endl; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /graph-theory/cses_1667.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n, m; 9 | cin >> n >> m; 10 | 11 | vector> adj(n + 1); 12 | vector dist(n + 1, -1); 13 | vector prev(n + 1, -1); 14 | 15 | for (int i = 0; i < m; ++i) { 16 | int a, b; 17 | cin >> a >> b; 18 | adj[a].push_back(b); 19 | adj[b].push_back(a); 20 | } 21 | 22 | queue q; 23 | q.push(1); 24 | dist[1] = 1; // Starting node distance is 1 because we include the start node in the count 25 | 26 | while (!q.empty()) { 27 | int node = q.front(); 28 | q.pop(); 29 | 30 | for (int neighbor : adj[node]) { 31 | if (dist[neighbor] == -1) { // If the neighbor has not been visited 32 | dist[neighbor] = dist[node] + 1; 33 | prev[neighbor] = node; 34 | q.push(neighbor); 35 | 36 | // If we reached the target node, we can stop early 37 | if (neighbor == n) { 38 | break; 39 | } 40 | } 41 | } 42 | } 43 | 44 | if (dist[n] == -1) { 45 | cout << "IMPOSSIBLE" << endl; 46 | } else { 47 | cout << dist[n] << endl; 48 | vector path; 49 | for (int at = n; at != -1; at = prev[at]) { 50 | path.push_back(at); 51 | } 52 | reverse(path.begin(), path.end()); 53 | for (int node : path) { 54 | cout << node << " "; 55 | } 56 | cout << endl; 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /graph-theory/cses_1668.cpp: -------------------------------------------------------------------------------- 1 | // https://cses.fi/problemset/task/1668 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | bool bfs(int start, vector>& adj, vector& team) { 10 | queue q; 11 | q.push(start); 12 | team[start] = 1; // Assign team 1 to the start node 13 | 14 | while (!q.empty()) { 15 | int u = q.front(); 16 | q.pop(); 17 | 18 | for (int v : adj[u]) { 19 | if (team[v] == 0) { 20 | // Assign the opposite team to the adjacent node 21 | team[v] = 3 - team[u]; 22 | q.push(v); 23 | } else if (team[v] == team[u]) { 24 | // If the adjacent node has the same team, the graph is not bipartite 25 | return false; 26 | } 27 | } 28 | } 29 | 30 | return true; 31 | } 32 | 33 | int main() { 34 | int n, m; 35 | cin >> n >> m; 36 | 37 | vector> adj(n + 1); // Adjacency list for the graph 38 | vector team(n + 1, 0); // Team assignment for each pupil, 0 means unassigned 39 | 40 | for (int i = 0; i < m; ++i) { 41 | int a, b; 42 | cin >> a >> b; 43 | adj[a].push_back(b); 44 | adj[b].push_back(a); 45 | } 46 | 47 | // Try to color the graph using BFS 48 | for (int i = 1; i <= n; ++i) { 49 | if (team[i] == 0) { // If the node is unassigned, perform BFS 50 | if (!bfs(i, adj, team)) { 51 | cout << "IMPOSSIBLE" << endl; 52 | return 0; 53 | } 54 | } 55 | } 56 | 57 | // If the graph is bipartite, print the team assignment 58 | for (int i = 1; i <= n; ++i) { 59 | cout << team[i] << " \n"[i == n]; 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /graph-theory/cses_1669.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | bool dfs(int node, int parent, const vector>& adj, vector& visited, vector& parent_track, int& cycle_start, int& cycle_end) { 8 | visited[node] = 1; // Mark node as visited 9 | for (int neighbor : adj[node]) { 10 | if (neighbor == parent) continue; // Ignore the edge to the parent node 11 | if (visited[neighbor]) { 12 | // Cycle found 13 | cycle_start = neighbor; 14 | cycle_end = node; 15 | return true; 16 | } 17 | parent_track[neighbor] = node; 18 | if (dfs(neighbor, node, adj, visited, parent_track, cycle_start, cycle_end)) { 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | 25 | int main() { 26 | int n, m; 27 | cin >> n >> m; 28 | 29 | vector> adj(n + 1); 30 | for (int i = 0; i < m; ++i) { 31 | int a, b; 32 | cin >> a >> b; 33 | adj[a].push_back(b); 34 | adj[b].push_back(a); 35 | } 36 | 37 | vector visited(n + 1, 0); 38 | vector parent_track(n + 1, -1); 39 | int cycle_start = -1, cycle_end = -1; 40 | 41 | for (int i = 1; i <= n; ++i) { 42 | if (!visited[i]) { 43 | if (dfs(i, -1, adj, visited, parent_track, cycle_start, cycle_end)) { 44 | break; 45 | } 46 | } 47 | } 48 | 49 | if (cycle_start == -1) { 50 | cout << "IMPOSSIBLE" << endl; 51 | } else { 52 | vector cycle; 53 | cycle.push_back(cycle_start); 54 | for (int v = cycle_end; v != cycle_start; v = parent_track[v]) { 55 | cycle.push_back(v); 56 | } 57 | cycle.push_back(cycle_start); 58 | reverse(cycle.begin(), cycle.end()); 59 | 60 | cout << cycle.size() << endl; 61 | for (int v : cycle) { 62 | cout << v << " "; 63 | } 64 | cout << endl; 65 | } 66 | 67 | return 0; 68 | } 69 | // g++ -std=c++17 cses_1669.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_1671.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const long long INF = LLONG_MAX; 9 | 10 | struct Edge { 11 | int to; 12 | long long cost; 13 | }; 14 | 15 | int main() { 16 | int n, m; 17 | cin >> n >> m; 18 | 19 | vector> graph(n + 1); 20 | for (int i = 0; i < m; ++i) { 21 | int a, b; 22 | long long c; 23 | cin >> a >> b >> c; 24 | graph[a].push_back({b, c}); 25 | } 26 | 27 | vector dist(n + 1, INF); 28 | dist[1] = 0; 29 | 30 | priority_queue, vector>, greater>> pq; 31 | pq.push({0, 1}); 32 | 33 | while (!pq.empty()) { 34 | auto [d, u] = pq.top(); 35 | pq.pop(); 36 | 37 | if (d > dist[u]) continue; 38 | 39 | for (auto& edge : graph[u]) { 40 | int v = edge.to; 41 | long long cost = edge.cost; 42 | 43 | if (dist[u] + cost < dist[v]) { 44 | dist[v] = dist[u] + cost; 45 | pq.push({dist[v], v}); 46 | } 47 | } 48 | } 49 | 50 | for (int i = 1; i <= n; ++i) { 51 | cout << dist[i] << " "; 52 | } 53 | cout << endl; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /graph-theory/cses_1672.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const long long INF = 1e18; 8 | 9 | int main() { 10 | int n, m, q; 11 | cin >> n >> m >> q; 12 | 13 | vector> dist(n + 1, vector(n + 1, INF)); 14 | 15 | for (int i = 1; i <= n; ++i) { 16 | dist[i][i] = 0; 17 | } 18 | 19 | for (int i = 0; i < m; ++i) { 20 | int a, b; 21 | long long c; 22 | cin >> a >> b >> c; 23 | dist[a][b] = min(dist[a][b], c); 24 | dist[b][a] = min(dist[b][a], c); 25 | } 26 | 27 | // Floyd-Warshall algorithm 28 | for (int k = 1; k <= n; ++k) { 29 | for (int i = 1; i <= n; ++i) { 30 | for (int j = 1; j <= n; ++j) { 31 | if (dist[i][k] < INF && dist[k][j] < INF) { 32 | dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); 33 | } 34 | } 35 | } 36 | } 37 | 38 | for (int i = 0; i < q; ++i) { 39 | int a, b; 40 | cin >> a >> b; 41 | if (dist[a][b] == INF) { 42 | cout << -1 << endl; 43 | } else { 44 | cout << dist[a][b] << endl; 45 | } 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /graph-theory/cses_1674.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void dfs(int employee, const vector>& subordinates, vector& subordinate_count) { 7 | for (int subordinate : subordinates[employee]) { 8 | dfs(subordinate, subordinates, subordinate_count); 9 | subordinate_count[employee] += 1 + subordinate_count[subordinate]; 10 | } 11 | } 12 | 13 | int main() { 14 | int n; 15 | cin >> n; 16 | 17 | vector> subordinates(n + 1); // subordinates[i] stores the list of direct subordinates of employee i 18 | vector subordinate_count(n + 1, 0); // subordinate_count[i] stores the count of all subordinates of employee i 19 | 20 | // Reading input: each employee's boss 21 | for (int i = 2; i <= n; i++) { 22 | int boss; 23 | cin >> boss; 24 | subordinates[boss].push_back(i); 25 | } 26 | 27 | // Perform DFS starting from the general director (employee 1) 28 | dfs(1, subordinates, subordinate_count); 29 | 30 | // Output the results for all employees from 1 to n 31 | for (int i = 1; i <= n; i++) { 32 | cout << subordinate_count[i] << " "; 33 | } 34 | cout << endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /graph-theory/cses_1675.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Edge { 7 | int u, v, cost; 8 | bool operator<(const Edge& other) const { 9 | return cost < other.cost; 10 | } 11 | }; 12 | 13 | vector parent, rnk; 14 | 15 | int find(int x) { 16 | if (parent[x] != x) 17 | parent[x] = find(parent[x]); 18 | return parent[x]; 19 | } 20 | 21 | void unionSet(int x, int y) { 22 | int rootX = find(x); 23 | int rootY = find(y); 24 | 25 | if (rootX != rootY) { 26 | if (rnk[rootX] > rnk[rootY]) { 27 | parent[rootY] = rootX; 28 | } else if (rnk[rootX] < rnk[rootY]) { 29 | parent[rootX] = rootY; 30 | } else { 31 | parent[rootY] = rootX; 32 | rnk[rootX]++; 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | ios::sync_with_stdio(false); 39 | cin.tie(nullptr); 40 | 41 | int n, m; 42 | cin >> n >> m; 43 | 44 | vector edges(m); 45 | for (int i = 0; i < m; ++i) { 46 | cin >> edges[i].u >> edges[i].v >> edges[i].cost; 47 | --edges[i].u; 48 | --edges[i].v; 49 | } 50 | 51 | sort(edges.begin(), edges.end()); 52 | 53 | parent.resize(n); 54 | rnk.resize(n, 0); 55 | for (int i = 0; i < n; ++i) { 56 | parent[i] = i; 57 | } 58 | 59 | long long totalCost = 0; 60 | int edgeCount = 0; 61 | 62 | for (const Edge& e : edges) { 63 | int rootU = find(e.u); 64 | int rootV = find(e.v); 65 | 66 | if (rootU != rootV) { 67 | unionSet(rootU, rootV); 68 | totalCost += e.cost; 69 | edgeCount++; 70 | } 71 | 72 | if (edgeCount == n - 1) { 73 | break; 74 | } 75 | } 76 | 77 | if (edgeCount == n - 1) { 78 | cout << totalCost << "\n"; 79 | } else { 80 | cout << "IMPOSSIBLE\n"; 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /graph-theory/cses_1678.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | vector> adj; 9 | vector visited, parent; 10 | int start, end_cycle; 11 | 12 | bool dfs(int v) { 13 | visited[v] = 1; 14 | for (int u : adj[v]) { 15 | if (!visited[u]) { 16 | parent[u] = v; 17 | if (dfs(u)) { 18 | return true; 19 | } 20 | } else if (visited[u] == 1) { 21 | start = u; 22 | end_cycle = v; 23 | return true; 24 | } 25 | } 26 | visited[v] = 2; 27 | return false; 28 | } 29 | 30 | int main() { 31 | int n, m; 32 | cin >> n >> m; 33 | 34 | adj.resize(n + 1); 35 | visited.assign(n + 1, 0); 36 | parent.assign(n + 1, -1); 37 | 38 | for (int i = 0; i < m; ++i) { 39 | int a, b; 40 | cin >> a >> b; 41 | adj[a].push_back(b); 42 | } 43 | 44 | start = -1; 45 | for (int i = 1; i <= n; ++i) { 46 | if (!visited[i] && dfs(i)) { 47 | break; 48 | } 49 | } 50 | 51 | if (start == -1) { 52 | cout << "IMPOSSIBLE" << endl; 53 | } else { 54 | vector cycle; 55 | cycle.push_back(start); 56 | for (int v = end_cycle; v != start; v = parent[v]) { 57 | cycle.push_back(v); 58 | } 59 | cycle.push_back(start); 60 | reverse(cycle.begin(), cycle.end()); 61 | 62 | cout << cycle.size() << endl; 63 | for (int v : cycle) { 64 | cout << v << " "; 65 | } 66 | cout << endl; 67 | } 68 | 69 | return 0; 70 | } 71 | // g++ -std=c++17 -O2 -Wall cses_1678.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_1679.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void findCourseOrder(int n, int m, vector> &edges) { 8 | vector> graph(n + 1); 9 | vector in_degree(n + 1, 0); 10 | 11 | // Build the graph and in-degree array 12 | for (auto edge : edges) { 13 | int a = edge.first; 14 | int b = edge.second; 15 | graph[a].push_back(b); 16 | in_degree[b]++; 17 | } 18 | 19 | queue q; 20 | vector order; 21 | 22 | // Add all nodes with in-degree 0 to the queue 23 | for (int i = 1; i <= n; i++) { 24 | if (in_degree[i] == 0) { 25 | q.push(i); 26 | } 27 | } 28 | 29 | while (!q.empty()) { 30 | int node = q.front(); 31 | q.pop(); 32 | order.push_back(node); 33 | 34 | for (int neighbor : graph[node]) { 35 | in_degree[neighbor]--; 36 | if (in_degree[neighbor] == 0) { 37 | q.push(neighbor); 38 | } 39 | } 40 | } 41 | 42 | // If we processed all nodes, we have a valid topological order 43 | if (order.size() == n) { 44 | for (int course : order) { 45 | cout << course << " "; 46 | } 47 | cout << endl; 48 | } else { 49 | cout << "IMPOSSIBLE" << endl; 50 | } 51 | } 52 | 53 | int main() { 54 | int n, m; 55 | cin >> n >> m; 56 | vector> edges(m); 57 | 58 | for (int i = 0; i < m; i++) { 59 | cin >> edges[i].first >> edges[i].second; 60 | } 61 | 62 | findCourseOrder(n, m, edges); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /graph-theory/cses_1681.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int MOD = 1e9 + 7; 8 | 9 | void findWays(int n, int m, vector>& edges) { 10 | vector> adj(n + 1); 11 | vector indegree(n + 1, 0); 12 | 13 | // Build the adjacency list and calculate indegrees 14 | for (auto edge : edges) { 15 | int a = edge.first, b = edge.second; 16 | adj[a].push_back(b); 17 | indegree[b]++; 18 | } 19 | 20 | // Topological sort using Kahn's algorithm 21 | queue q; 22 | for (int i = 1; i <= n; i++) { 23 | if (indegree[i] == 0) { 24 | q.push(i); 25 | } 26 | } 27 | 28 | vector topo_order; 29 | while (!q.empty()) { 30 | int u = q.front(); 31 | q.pop(); 32 | topo_order.push_back(u); 33 | 34 | for (int v : adj[u]) { 35 | indegree[v]--; 36 | if (indegree[v] == 0) { 37 | q.push(v); 38 | } 39 | } 40 | } 41 | 42 | // Initialize the dp array 43 | vector dp(n + 1, 0); 44 | dp[1] = 1; 45 | 46 | // Process nodes in topological order 47 | for (int u : topo_order) { 48 | for (int v : adj[u]) { 49 | dp[v] = (dp[v] + dp[u]) % MOD; 50 | } 51 | } 52 | 53 | // Output the number of ways to reach level n 54 | cout << dp[n] << endl; 55 | } 56 | 57 | int main() { 58 | int n, m; 59 | cin >> n >> m; 60 | vector> edges(m); 61 | for (int i = 0; i < m; i++) { 62 | cin >> edges[i].first >> edges[i].second; 63 | } 64 | findWays(n, m, edges); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /graph-theory/cses_1682_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | vector> graph, reverseGraph; 6 | vector visited; 7 | 8 | void dfs(int node, const vector> &adj) { 9 | visited[node] = true; 10 | for (int neighbor : adj[node]) { 11 | if (!visited[neighbor]) { 12 | dfs(neighbor, adj); 13 | } 14 | } 15 | } 16 | 17 | int main() { 18 | int n, m; 19 | cin >> n >> m; 20 | 21 | graph.resize(n + 1); 22 | reverseGraph.resize(n + 1); 23 | 24 | // Input the flight connections 25 | for (int i = 0; i < m; i++) { 26 | int a, b; 27 | cin >> a >> b; 28 | graph[a].push_back(b); 29 | reverseGraph[b].push_back(a); // Reverse the direction of edges 30 | } 31 | 32 | // Step 1: Check if all nodes are reachable from node 1 33 | visited.assign(n + 1, false); 34 | dfs(1, graph); 35 | for (int i = 1; i <= n; i++) { 36 | if (!visited[i]) { 37 | cout << "NO\n" << "1 " << i << "\n"; 38 | return 0; 39 | } 40 | } 41 | 42 | // Step 2: Check if all nodes can reach node 1 (reverse graph) 43 | visited.assign(n + 1, false); 44 | dfs(1, reverseGraph); 45 | for (int i = 1; i <= n; i++) { 46 | if (!visited[i]) { 47 | cout << "NO\n" << i << " 1\n"; 48 | return 0; 49 | } 50 | } 51 | 52 | // If both checks pass, the graph is strongly connected 53 | cout << "YES\n"; 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /graph-theory/cses_1683.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int MAXN = 100000; 9 | vector graph[MAXN], reverseGraph[MAXN]; 10 | vector scc[MAXN]; 11 | bool visited[MAXN]; 12 | stack nodesStack; 13 | int component[MAXN]; 14 | int n, m; 15 | 16 | void dfs1(int u) { 17 | visited[u] = true; 18 | for (int v : graph[u]) { 19 | if (!visited[v]) { 20 | dfs1(v); 21 | } 22 | } 23 | nodesStack.push(u); 24 | } 25 | 26 | void dfs2(int u, int comp) { 27 | visited[u] = true; 28 | component[u] = comp; 29 | scc[comp].push_back(u); 30 | for (int v : reverseGraph[u]) { 31 | if (!visited[v]) { 32 | dfs2(v, comp); 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | ios::sync_with_stdio(false); 39 | cin.tie(nullptr); 40 | 41 | cin >> n >> m; 42 | 43 | for (int i = 0; i < m; ++i) { 44 | int a, b; 45 | cin >> a >> b; 46 | --a; --b; // Convert to 0-based indexing 47 | graph[a].push_back(b); 48 | reverseGraph[b].push_back(a); 49 | } 50 | 51 | // Step 1: Perform DFS to get finishing times 52 | fill(visited, visited + n, false); 53 | for (int i = 0; i < n; ++i) { 54 | if (!visited[i]) { 55 | dfs1(i); 56 | } 57 | } 58 | 59 | // Step 2: Reverse DFS using finish times to find SCCs 60 | fill(visited, visited + n, false); 61 | int compCount = 0; 62 | while (!nodesStack.empty()) { 63 | int u = nodesStack.top(); 64 | nodesStack.pop(); 65 | if (!visited[u]) { 66 | dfs2(u, compCount++); 67 | } 68 | } 69 | 70 | // Output results 71 | cout << compCount << endl; 72 | for (int i = 0; i < n; ++i) { 73 | cout << component[i] + 1 << " "; // Convert back to 1-based indexing 74 | } 75 | cout << endl; 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /graph-theory/cses_1687.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int LOG = 18; // log2(200000) ~ 17.6, so we use 18 for safety 8 | 9 | vector> up; 10 | vector depth; 11 | 12 | void preprocess(int n, const vector& boss) { 13 | up.assign(n + 1, vector(LOG + 1, -1)); 14 | depth.assign(n + 1, 0); 15 | 16 | for (int i = 2; i <= n; ++i) { 17 | up[i][0] = boss[i-2]; // boss[i] is the direct boss of employee i+1 18 | depth[i] = depth[boss[i-2]] + 1; 19 | } 20 | 21 | for (int j = 1; j <= LOG; ++j) { 22 | for (int i = 1; i <= n; ++i) { 23 | if (up[i][j-1] != -1) { 24 | up[i][j] = up[up[i][j-1]][j-1]; 25 | } 26 | } 27 | } 28 | } 29 | 30 | int get_kth_ancestor(int x, int k) { 31 | if (depth[x] < k) return -1; 32 | 33 | for (int j = LOG; j >= 0; --j) { 34 | if ((k >> j) & 1) { 35 | x = up[x][j]; 36 | if (x == -1) return -1; 37 | } 38 | } 39 | return x; 40 | } 41 | 42 | int main() { 43 | int n, q; 44 | cin >> n >> q; 45 | 46 | vector boss(n - 1); 47 | for (int i = 0; i < n - 1; ++i) { 48 | cin >> boss[i]; 49 | } 50 | 51 | preprocess(n, boss); 52 | 53 | for (int i = 0; i < q; ++i) { 54 | int x, k; 55 | cin >> x >> k; 56 | cout << get_kth_ancestor(x, k) << endl; 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /graph-theory/cses_1688.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int LOG = 18; // log2(200000) ~ 17.6, so we use 18 for safety 7 | 8 | vector> up; 9 | vector depth; 10 | 11 | void preprocess(int n, const vector& boss) { 12 | up.assign(n + 1, vector(LOG + 1, -1)); 13 | depth.assign(n + 1, 0); 14 | 15 | for (int i = 2; i <= n; ++i) { 16 | up[i][0] = boss[i - 2]; // boss[i] is the direct boss of employee i+1 17 | depth[i] = depth[boss[i - 2]] + 1; 18 | } 19 | 20 | for (int j = 1; j <= LOG; ++j) { 21 | for (int i = 1; i <= n; ++i) { 22 | if (up[i][j - 1] != -1) { 23 | up[i][j] = up[up[i][j - 1]][j - 1]; 24 | } 25 | } 26 | } 27 | } 28 | 29 | int lca(int a, int b) { 30 | if (depth[a] < depth[b]) { 31 | swap(a, b); 32 | } 33 | 34 | // Lift a to the same level as b 35 | for (int j = LOG; j >= 0; --j) { 36 | if (depth[a] - (1 << j) >= depth[b]) { 37 | a = up[a][j]; 38 | } 39 | } 40 | 41 | if (a == b) { 42 | return a; 43 | } 44 | 45 | // Lift both a and b up until they meet 46 | for (int j = LOG; j >= 0; --j) { 47 | if (up[a][j] != -1 && up[a][j] != up[b][j]) { 48 | a = up[a][j]; 49 | b = up[b][j]; 50 | } 51 | } 52 | 53 | // Their LCA is the parent of the node they both reached 54 | return up[a][0]; 55 | } 56 | 57 | int main() { 58 | int n, q; 59 | cin >> n >> q; 60 | 61 | vector boss(n - 1); 62 | for (int i = 0; i < n - 1; ++i) { 63 | cin >> boss[i]; 64 | } 65 | 66 | preprocess(n, boss); 67 | 68 | for (int i = 0; i < q; ++i) { 69 | int a, b; 70 | cin >> a >> b; 71 | cout << lca(a, b) << endl; 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /graph-theory/cses_1692.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void de_bruijn(string& result, const string& alphabet, int n, int k) { 7 | vector a(k * n); 8 | for (int i = 0; i < k * n; ++i) { 9 | a[i] = 0; 10 | } 11 | result = ""; 12 | int j = 1; 13 | while (j <= n) { 14 | a[j] = 1; 15 | int i = 1; 16 | while (i <= j) { 17 | result += alphabet[a[i]]; 18 | ++i; 19 | } 20 | while (a[j] == k - 1) { 21 | a[j] = 0; 22 | --j; 23 | } 24 | ++a[j]; 25 | ++j; 26 | } 27 | } 28 | 29 | int main() { 30 | int n; 31 | cin >> n; 32 | 33 | if (n < 1 || n > 15) { 34 | cerr << "Invalid input" << endl; 35 | return 1; 36 | } 37 | 38 | string alphabet = "01"; 39 | string result; 40 | 41 | de_bruijn(result, alphabet, n, 2); 42 | 43 | // To convert cyclic to linear, append first n-1 characters to the end 44 | result += result.substr(0, n - 1); 45 | 46 | cout << result << endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /graph-theory/cses_1723.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MOD 1000000007 4 | using namespace std; 5 | 6 | // Define matrix type 7 | typedef vector> Matrix; 8 | 9 | // Function to multiply two matrices 10 | Matrix matMul(const Matrix &a, const Matrix &b, int n) { 11 | Matrix result(n, vector(n, 0)); 12 | for (int i = 0; i < n; ++i) { 13 | for (int j = 0; j < n; ++j) { 14 | for (int k = 0; k < n; ++k) { 15 | result[i][j] = (result[i][j] + a[i][k] * b[k][j]) % MOD; 16 | } 17 | } 18 | } 19 | return result; 20 | } 21 | 22 | // Function to perform matrix exponentiation 23 | Matrix matPow(Matrix base, long long exp, int n) { 24 | Matrix result(n, vector(n, 0)); 25 | // Initialize result as the identity matrix 26 | for (int i = 0; i < n; ++i) { 27 | result[i][i] = 1; 28 | } 29 | // Perform exponentiation 30 | while (exp > 0) { 31 | if (exp % 2 == 1) { 32 | result = matMul(result, base, n); 33 | } 34 | base = matMul(base, base, n); 35 | exp /= 2; 36 | } 37 | return result; 38 | } 39 | 40 | int main() { 41 | int n, m; 42 | long long k; 43 | cin >> n >> m >> k; 44 | 45 | // Initialize adjacency matrix 46 | Matrix adj(n, vector(n, 0)); 47 | 48 | // Read edges 49 | for (int i = 0; i < m; ++i) { 50 | int a, b; 51 | cin >> a >> b; 52 | --a; --b; // Convert to 0-based indexing 53 | adj[a][b] = (adj[a][b] + 1) % MOD; 54 | } 55 | 56 | // Exponentiate the adjacency matrix 57 | Matrix result = matPow(adj, k, n); 58 | 59 | // The result is the number of paths from node 1 to node n 60 | cout << result[0][n-1] << endl; 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /graph-theory/cses_1750.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MAX_L = 30; // 2^32 is larger than 10^9, suffices for k <= 10^9 6 | const int MAXN = 2e5 + 5; 7 | int lift[MAXN][MAX_L]; 8 | 9 | int main() { 10 | ios::sync_with_stdio(false); 11 | cin.tie(nullptr); 12 | 13 | int n, q; 14 | cin >> n >> q; 15 | 16 | vector teleports(n + 1); 17 | for (int i = 1; i <= n; ++i) { 18 | cin >> teleports[i]; 19 | } 20 | 21 | // vector> lift(n + 1, vector(MAX_L)); 22 | 23 | // Initialize the lift table 24 | for (int i = 1; i <= n; ++i) { 25 | lift[i][0] = teleports[i]; 26 | } 27 | 28 | // Fill the table 29 | for (int j = 1; j < MAX_L; ++j) { 30 | for (int i = 1; i <= n; ++i) { 31 | lift[i][j] = lift[lift[i][j-1]][j-1]; 32 | } 33 | } 34 | 35 | while (q--) { 36 | int x, k; 37 | cin >> x >> k; 38 | int current = x; 39 | 40 | for (int j = 0; j < MAX_L; ++j) { 41 | if (k & (1 << j)) { 42 | current = lift[current][j]; 43 | } 44 | } 45 | 46 | cout << current << "\n"; 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /graph-theory/cses_1751.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | vector teleporters, result, visited, cycle_size; 7 | 8 | // DFS function to compute teleportation counts 9 | int dfs(int planet) { 10 | if (visited[planet] == 1) { 11 | // We found a cycle 12 | visited[planet] = 2; 13 | int cycle_start = planet, cycle_length = 1; 14 | int next = teleporters[planet]; 15 | while (next != cycle_start) { 16 | visited[next] = 2; 17 | next = teleporters[next]; 18 | cycle_length++; 19 | } 20 | 21 | // Assign cycle length to all planets in the cycle 22 | next = planet; 23 | do { 24 | result[next] = cycle_length; 25 | next = teleporters[next]; 26 | } while (next != cycle_start); 27 | 28 | return cycle_length; 29 | } 30 | 31 | if (visited[planet] == 2) { 32 | // Planet already fully processed (part of a known cycle or result) 33 | return result[planet]; 34 | } 35 | 36 | visited[planet] = 1; // Mark as visited (in-progress) 37 | int next = teleporters[planet]; 38 | int total_steps = dfs(next) + 1; // Move to next planet 39 | 40 | visited[planet] = 2; // Mark as fully processed 41 | result[planet] = total_steps; 42 | return total_steps; 43 | } 44 | 45 | int main() { 46 | int n; 47 | cin >> n; 48 | 49 | teleporters.resize(n + 1); 50 | result.resize(n + 1); 51 | visited.resize(n + 1, 0); 52 | 53 | for (int i = 1; i <= n; ++i) { 54 | cin >> teleporters[i]; 55 | } 56 | 57 | // Process each planet using DFS 58 | for (int i = 1; i <= n; ++i) { 59 | if (visited[i] == 0) { 60 | dfs(i); 61 | } 62 | } 63 | 64 | // Output the results 65 | for (int i = 1; i <= n; ++i) { 66 | cout << result[i] << " "; 67 | } 68 | cout << endl; 69 | 70 | return 0; 71 | } 72 | 73 | // g++ -std=c++17 -O2 -Wall cses_1751.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /graph-theory/cses_2079.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MAXN = 200005; 6 | int n; 7 | vector adj[MAXN]; 8 | int subtree_size[MAXN]; 9 | 10 | void dfs(int u, int parent, int& centroid, int total_nodes) { 11 | subtree_size[u] = 1; 12 | bool is_centroid = true; 13 | 14 | for (int v : adj[u]) { 15 | if (v == parent) continue; 16 | dfs(v, u, centroid, total_nodes); 17 | subtree_size[u] += subtree_size[v]; 18 | 19 | // Check if the current node u can be a centroid 20 | if (subtree_size[v] > total_nodes / 2) { 21 | is_centroid = false; 22 | } 23 | } 24 | 25 | // Check the size of the "remaining" tree (outside of the subtree rooted at u) 26 | if (total_nodes - subtree_size[u] > total_nodes / 2) { 27 | is_centroid = false; 28 | } 29 | 30 | if (is_centroid) { 31 | centroid = u; 32 | } 33 | } 34 | 35 | int main() { 36 | ios::sync_with_stdio(false); 37 | cin.tie(0); 38 | 39 | cin >> n; 40 | for (int i = 0; i < n - 1; ++i) { 41 | int a, b; 42 | cin >> a >> b; 43 | adj[a].push_back(b); 44 | adj[b].push_back(a); 45 | } 46 | 47 | int centroid = -1; 48 | dfs(1, -1, centroid, n); 49 | 50 | cout << centroid << "\n"; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /graph-theory/cses_2080.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAXN = 200005; 7 | 8 | vector adj[MAXN]; 9 | int n, k; 10 | long long result = 0; 11 | 12 | void dfs(int u, int parent, map& dp) { 13 | dp[0] = 1; // There is 1 way to have a path of length 0 14 | 15 | for (int v : adj[u]) { 16 | if (v == parent) continue; 17 | 18 | map dp_child; 19 | dfs(v, u, dp_child); 20 | 21 | // Combine paths from dp and dp_child to form paths of length k 22 | for (auto [length, count] : dp_child) { 23 | if (length + 1 <= k) { 24 | result += count * dp[k - length - 1]; 25 | } 26 | } 27 | 28 | // Update dp to include paths ending at u from v 29 | for (auto [length, count] : dp_child) { 30 | dp[length + 1] += count; 31 | } 32 | } 33 | } 34 | 35 | int main() { 36 | ios::sync_with_stdio(false); 37 | cin.tie(0); 38 | 39 | cin >> n >> k; 40 | 41 | for (int i = 0; i < n - 1; ++i) { 42 | int a, b; 43 | cin >> a >> b; 44 | adj[a].push_back(b); 45 | adj[b].push_back(a); 46 | } 47 | 48 | map dp; 49 | dfs(1, -1, dp); 50 | 51 | cout << result << "\n"; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /graph-theory/dsu/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtuann/competitive-programming-101/6d2aa5ea11b9df761a91c996358454760d1b9292/graph-theory/dsu/a -------------------------------------------------------------------------------- /graph-theory/dsu/cses1676.cpp: -------------------------------------------------------------------------------- 1 | // https://cses.fi/problemset/task/1676 2 | // https://cses.fi/problemset/result/9464662/ 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int N = 1e5 + 5; 9 | int n, m; 10 | 11 | class DSU { 12 | vector parent; // parent of each node: if parent[i] = i, then i is the root 13 | vector sz; // size of each set 14 | 15 | public: 16 | DSU(int n) { 17 | parent.resize(n); 18 | sz.resize(n); 19 | for (int i = 0; i < n; i++) { 20 | parent[i] = i; 21 | sz[i] = 1; 22 | } 23 | } 24 | 25 | int find(int x) { 26 | if (parent[x] != x) { 27 | parent[x] = find(parent[x]); 28 | } 29 | return parent[x]; 30 | } 31 | 32 | int get_size(int x) { 33 | return sz[find(x)]; 34 | } 35 | 36 | void union_set(int x, int y) { 37 | int px = find(x); 38 | int py = find(y); 39 | if (px == py) return; 40 | if (sz[px] < sz[py]) swap(px, py); 41 | parent[py] = px; 42 | sz[px] += sz[py]; 43 | } 44 | }; 45 | 46 | int main() { 47 | cin.tie(0)->sync_with_stdio(0); 48 | 49 | cin >> n >> m; 50 | 51 | DSU dsu(n); 52 | int total = n, max_size = 1; 53 | for (int i = 0; i < m; i++) { 54 | int u, v; 55 | cin >> u >> v; 56 | u--; v--; 57 | if (dsu.find(u) == dsu.find(v)) { 58 | cout << total << ' ' << max_size << '\n'; 59 | continue; 60 | } else { 61 | total--; 62 | dsu.union_set(u, v); 63 | max_size = max(max_size, dsu.get_size(u)); 64 | cout << total << ' ' << max_size << '\n'; 65 | } 66 | } 67 | return 0; 68 | } 69 | // g++ -std=c++17 -o a cses1676.cpp && ./a 70 | 71 | -------------------------------------------------------------------------------- /graph-theory/dsu/dsu.cpp: -------------------------------------------------------------------------------- 1 | // write disjoin set union find 2 | // Time Complexity: O(logn) for find and O(1) for union 3 | // Space Complexity: O(n) 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | class DSU { 9 | vector parent; // parent of each node: if parent[i] = i, then i is the root 10 | vector rank; // rank is used to keep the tree balanced 11 | public: 12 | DSU(int n) { 13 | parent.resize(n); 14 | rank.resize(n); 15 | for (int i = 0; i < n; i++) { 16 | parent[i] = i; 17 | rank[i] = 0; 18 | } 19 | } 20 | 21 | int find(int x) { 22 | if (parent[x] != x) { 23 | parent[x] = find(parent[x]); 24 | } 25 | return parent[x]; 26 | } 27 | 28 | void union_set(int x, int y) { 29 | int px = find(x); 30 | int py = find(y); 31 | if (px == py) return; 32 | if (rank[px] < rank[py]) { 33 | parent[px] = py; 34 | } else if (rank[px] > rank[py]) { 35 | parent[py] = px; 36 | } else { 37 | parent[px] = py; 38 | rank[py]++; 39 | } 40 | } 41 | }; 42 | 43 | int main() { 44 | DSU dsu(5); 45 | dsu.union_set(0, 1); 46 | dsu.union_set(1, 2); 47 | dsu.union_set(3, 4); 48 | cout << dsu.find(0) << endl; 49 | cout << dsu.find(2) << endl; 50 | cout << dsu.find(3) << endl; 51 | return 0; 52 | } 53 | 54 | // clang++ -std=c++17 -o dsu dsu.cpp 55 | -------------------------------------------------------------------------------- /graph-theory/floyd_warshall.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void floydWarshall(vector>& graph, int n) { 8 | vector> dist = graph; 9 | 10 | for (int k = 0; k < n; ++k) { 11 | for (int i = 0; i < n; ++i) { 12 | for (int j = 0; j < n; ++j) { 13 | if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX && dist[i][k] + dist[k][j] < dist[i][j]) { 14 | dist[i][j] = dist[i][k] + dist[k][j]; 15 | } 16 | } 17 | } 18 | } 19 | 20 | cout << "The following matrix shows the shortest distances between every pair of vertices:\n"; 21 | for (int i = 0; i < n; ++i) { 22 | for (int j = 0; j < n; ++j) { 23 | if (dist[i][j] == INT_MAX) { 24 | cout << "INF "; 25 | } else { 26 | cout << dist[i][j] << " "; 27 | } 28 | } 29 | cout << endl; 30 | } 31 | } 32 | 33 | int main() { 34 | int n, m; 35 | cout << "Enter the number of vertices (n): "; 36 | cin >> n; 37 | cout << "Enter the number of edges (m): "; 38 | cin >> m; 39 | 40 | vector> graph(n, vector(n, INT_MAX)); 41 | 42 | for (int i = 0; i < n; ++i) { 43 | graph[i][i] = 0; 44 | } 45 | 46 | cout << "Enter the edges (u v w) where u and v are vertices (0-based index) and w is the weight:\n"; 47 | for (int i = 0; i < m; ++i) { 48 | int u, v, w; 49 | cin >> u >> v >> w; 50 | graph[u][v] = w; 51 | } 52 | 53 | floydWarshall(graph, n); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /intro/cses_1068.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | ios::sync_with_stdio(false); 8 | cin.tie(0); 9 | 10 | int n; 11 | cin >> n; 12 | 13 | vector result; 14 | 15 | while (n != 1) { 16 | result.push_back(n); 17 | if (n % 2 == 0) { 18 | n /= 2; 19 | } else { 20 | n = 3 * n + 1; 21 | } 22 | } 23 | 24 | result.push_back(1); // Append the final 1 25 | 26 | for (size_t i = 0; i < result.size(); ++i) { 27 | if (i > 0) cout << " "; 28 | cout << result[i]; 29 | } 30 | cout << endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /intro/cses_1069.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | string s; 8 | cin >> s; 9 | 10 | if (s.empty()) { 11 | cout << 0 << endl; 12 | return 0; 13 | } 14 | 15 | int maxLength = 1; 16 | int currentLength = 1; 17 | char currentChar = s[0]; 18 | 19 | for (size_t i = 1; i < s.size(); ++i) { 20 | if (s[i] == currentChar) { 21 | ++currentLength; 22 | } else { 23 | maxLength = max(maxLength, currentLength); 24 | currentChar = s[i]; 25 | currentLength = 1; 26 | } 27 | } 28 | 29 | // Final check for the last repetition 30 | maxLength = max(maxLength, currentLength); 31 | 32 | cout << maxLength << endl; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /intro/cses_1070.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | 10 | // If n is 2 or 1, handle special cases 11 | if (n == 1) { 12 | cout << "1" << endl; 13 | return 0; 14 | } 15 | if (n == 2 || n == 3) { 16 | cout << "NO SOLUTION" << endl; 17 | return 0; 18 | } 19 | 20 | // Output even numbers first 21 | for (int i = 2; i <= n; i += 2) { 22 | cout << i << " "; 23 | } 24 | 25 | // Output odd numbers next 26 | for (int i = 1; i <= n; i += 2) { 27 | cout << i << " "; 28 | } 29 | 30 | cout << endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /intro/cses_1071.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | long long findNumber(int y, int x) { 7 | int layer = max(y, x); 8 | long long start = (long long)(layer - 1) * (layer - 1) + 1; 9 | // long long end = layer * layer; 10 | 11 | if (layer % 2 == 0) { 12 | // For even layer, starting from top-right 13 | if (x == layer) { 14 | return start + (y - 1); 15 | } else { 16 | return start + (layer - 1) * 2 - (x - 1); 17 | } 18 | } else { 19 | // For odd layer, starting from bottom-left 20 | if (y == layer) { 21 | return start + (x - 1); 22 | } else { 23 | return start + (layer - 1) * 2 - (y - 1); 24 | } 25 | } 26 | } 27 | 28 | int main() { 29 | int t; 30 | cin >> t; 31 | while (t--) { 32 | int y, x; 33 | cin >> y >> x; 34 | cout << findNumber(y, x) << endl; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /intro/cses_1072.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // Function to count the number of attacking pairs of knights on a k x k board 7 | long long countAttackingPairs(int k) { 8 | if (k < 3) return 0; 9 | 10 | long long count = 0; 11 | // Knights can attack in 8 possible ways 12 | int dx[8] = {2, 1, -1, -2, -2, -1, 1, 2}; 13 | int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1}; 14 | 15 | // Check each cell on the board 16 | for (int i = 1; i <= k; ++i) { 17 | for (int j = 1; j <= k; ++j) { 18 | for (int d = 0; d < 8; ++d) { 19 | int ni = i + dx[d]; 20 | int nj = j + dy[d]; 21 | if (ni >= 1 && ni <= k && nj >= 1 && nj <= k) { 22 | count++; 23 | } 24 | } 25 | } 26 | } 27 | 28 | // Each attacking pair is counted twice (once from each knight's perspective) 29 | return count / 2; 30 | } 31 | 32 | int main() { 33 | int n; 34 | cin >> n; 35 | 36 | vector results(n); 37 | 38 | for (int k = 1; k <= n; ++k) { 39 | long long totalPairs = (long long)k * k * (k * k - 1) / 2; 40 | long long attackingPairs = countAttackingPairs(k); 41 | results[k - 1] = totalPairs - attackingPairs; 42 | } 43 | 44 | for (const auto& result : results) { 45 | cout << result << endl; 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /intro/cses_1083.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | ios::sync_with_stdio(false); 7 | cin.tie(0); 8 | 9 | int n; 10 | cin >> n; 11 | 12 | long long expectedSum = (static_cast(n) * (n + 1)) / 2; 13 | long long actualSum = 0; 14 | int number; 15 | 16 | for (int i = 0; i < n - 1; ++i) { 17 | cin >> number; 18 | actualSum += number; 19 | } 20 | 21 | cout << (expectedSum - actualSum) << endl; 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /intro/cses_1092.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | 10 | // Calculate the sum of the first n natural numbers 11 | long long sum = (n * (n + 1)) / 2; 12 | 13 | // Check if the sum is even 14 | if (sum % 2 != 0) { 15 | cout << "NO" << endl; 16 | return 0; 17 | } 18 | 19 | long long target = sum / 2; 20 | vector set1, set2; 21 | long long current_sum = 0; 22 | 23 | // Use a greedy approach to find the first set 24 | for (int i = n; i >= 1; --i) { 25 | if (current_sum + i <= target) { 26 | current_sum += i; 27 | set1.push_back(i); 28 | } else { 29 | set2.push_back(i); 30 | } 31 | } 32 | 33 | cout << "YES" << endl; 34 | cout << set1.size() << endl; 35 | for (int num : set1) { 36 | cout << num << " "; 37 | } 38 | cout << endl; 39 | 40 | cout << set2.size() << endl; 41 | for (int num : set2) { 42 | cout << num << " "; 43 | } 44 | cout << endl; 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /intro/cses_1094.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | vector arr(n); 10 | 11 | for (int i = 0; i < n; ++i) { 12 | cin >> arr[i]; 13 | } 14 | 15 | long long moves = 0; 16 | 17 | // Ensure the array is non-decreasing 18 | for (int i = 1; i < n; ++i) { 19 | if (arr[i] < arr[i - 1]) { 20 | moves += arr[i - 1] - arr[i]; 21 | arr[i] = arr[i - 1]; // Update current element to be non-decreasing 22 | } 23 | } 24 | 25 | cout << moves << endl; 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /intro/cses_1617.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MOD = 1000000007; 5 | 6 | // Function to perform modular exponentiation 7 | long long modExp(long long base, long long exp, int mod) { 8 | long long result = 1; 9 | base = base % mod; // Handle base greater than mod 10 | 11 | while (exp > 0) { 12 | if (exp % 2 == 1) // If exp is odd, multiply base with result 13 | result = (result * base) % mod; 14 | 15 | exp = exp >> 1; // Divide exp by 2 16 | base = (base * base) % mod; // Square the base 17 | } 18 | 19 | return result; 20 | } 21 | 22 | int main() { 23 | int n; 24 | cin >> n; 25 | 26 | // Compute 2^n % (10^9 + 7) 27 | long long result = modExp(2, n, MOD); 28 | 29 | // Print the result 30 | cout << result << endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /intro/cses_1618.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int countTrailingZeros(int n) { 5 | int count = 0; 6 | // Count factors of 5 7 | while (n >= 5) { 8 | n /= 5; 9 | count += n; 10 | } 11 | return count; 12 | } 13 | 14 | int main() { 15 | int n; 16 | cin >> n; 17 | 18 | // Compute the number of trailing zeros in n! 19 | int result = countTrailingZeros(n); 20 | 21 | // Print the result 22 | cout << result << endl; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /intro/cses_1622.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void generatePermutations(string& s, int left, int right, set& permutations) { 10 | if (left == right) { 11 | permutations.insert(s); 12 | } else { 13 | for (int i = left; i <= right; ++i) { 14 | swap(s[left], s[i]); 15 | generatePermutations(s, left + 1, right, permutations); 16 | swap(s[left], s[i]); // backtrack 17 | } 18 | } 19 | } 20 | 21 | int main() { 22 | string s; 23 | cin >> s; 24 | 25 | set permutations; 26 | generatePermutations(s, 0, s.size() - 1, permutations); 27 | 28 | // Convert set to vector for sorting 29 | vector sortedPermutations(permutations.begin(), permutations.end()); 30 | sort(sortedPermutations.begin(), sortedPermutations.end()); 31 | 32 | // Output results 33 | cout << sortedPermutations.size() << endl; 34 | for (const string& perm : sortedPermutations) { 35 | cout << perm << endl; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /intro/cses_1623.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main() { 10 | int n; 11 | cin >> n; 12 | 13 | vector weights(n); 14 | long long totalSum = 0; 15 | for (int i = 0; i < n; ++i) { 16 | cin >> weights[i]; 17 | totalSum += weights[i]; 18 | } 19 | 20 | long long minDifference = LLONG_MAX; 21 | 22 | // Generate all subsets 23 | int numSubsets = 1 << n; // 2^n subsets 24 | for (int mask = 0; mask < numSubsets; ++mask) { 25 | long long subsetSum = 0; 26 | for (int i = 0; i < n; ++i) { 27 | if (mask & (1 << i)) { 28 | subsetSum += weights[i]; 29 | } 30 | } 31 | long long remainingSum = totalSum - subsetSum; 32 | minDifference = min(minDifference, abs(subsetSum - remainingSum)); 33 | } 34 | 35 | cout << minDifference << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /intro/cses_1624.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 8; 7 | int cnt = 0; 8 | 9 | vector> board(N, vector(N)); 10 | 11 | // Arrays to track columns and diagonals 12 | vector cols(N, false); 13 | vector diag1(2 * N, false); 14 | vector diag2(2 * N, false); 15 | 16 | void placeQueens(int row) { 17 | if (row == N) { 18 | cnt++; 19 | return; 20 | } 21 | 22 | for (int col = 0; col < N; ++col) { 23 | if (board[row][col] == '.' && !cols[col] && !diag1[row + col] && !diag2[row - col + N - 1]) { 24 | // Place the queen 25 | cols[col] = true; 26 | diag1[row + col] = true; 27 | diag2[row - col + N - 1] = true; 28 | 29 | // Recur to place the next queen 30 | placeQueens(row + 1); 31 | 32 | // Remove the queen 33 | cols[col] = false; 34 | diag1[row + col] = false; 35 | diag2[row - col + N - 1] = false; 36 | } 37 | } 38 | } 39 | 40 | int main() { 41 | for (int i = 0; i < N; ++i) { 42 | for (int j = 0; j < N; ++j) { 43 | cin >> board[i][j]; 44 | } 45 | } 46 | 47 | placeQueens(0); 48 | 49 | cout << cnt << endl; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /intro/cses_1625.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // Define the directions 7 | const int dx[] = {1, -1, 0, 0}; 8 | const int dy[] = {0, 0, -1, 1}; 9 | const char directions[] = {'D', 'U', 'L', 'R'}; 10 | 11 | int main() { 12 | string description; 13 | cin >> description; 14 | 15 | int n = 7; // Size of the grid 16 | int steps = description.size(); 17 | 18 | // Initialize the DP table 19 | vector>> dp(n, vector>(n, vector(steps + 1, 0))); 20 | dp[0][0][0] = 1; // Starting point 21 | 22 | for (int step = 0; step < steps; ++step) { 23 | char ch = description[step]; 24 | vector>> new_dp(n, vector>(n, vector(steps + 1, 0))); 25 | 26 | for (int x = 0; x < n; ++x) { 27 | for (int y = 0; y < n; ++y) { 28 | if (dp[x][y][step] > 0) { 29 | for (int d = 0; d < 4; ++d) { 30 | int nx = x + dx[d]; 31 | int ny = y + dy[d]; 32 | if (nx >= 0 && nx < n && ny >= 0 && ny < n) { 33 | if (ch == '?' || ch == directions[d]) { 34 | new_dp[nx][ny][step + 1] += dp[x][y][step]; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | dp = new_dp; 42 | } 43 | 44 | // The result is the number of ways to reach (6, 0) at step 48 45 | cout << dp[6][0][steps] << endl; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /intro/cses_1754.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | bool canEmptyPiles(long long a, long long b) { 5 | // Check if the total number of coins is divisible by 3 6 | if ((a + b) % 3 != 0) return false; 7 | 8 | // Check if neither pile exceeds twice the size of the other 9 | if (a > 2 * b || b > 2 * a) return false; 10 | 11 | return true; 12 | } 13 | 14 | int main() { 15 | int t; 16 | cin >> t; 17 | 18 | while (t--) { 19 | long long a, b; 20 | cin >> a >> b; 21 | 22 | if (canEmptyPiles(a, b)) { 23 | cout << "YES" << endl; 24 | } else { 25 | cout << "NO" << endl; 26 | } 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /intro/cses_1755.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | string constructPalindrome(const string& s) { 10 | unordered_map freq; 11 | 12 | // Count frequencies of each character 13 | for (char ch : s) { 14 | freq[ch]++; 15 | } 16 | 17 | string first_half; 18 | char odd_char = '\0'; 19 | 20 | // Determine if we can create a palindrome 21 | for (const auto& pair : freq) { 22 | char ch = pair.first; 23 | int count = pair.second; 24 | 25 | if (count % 2 != 0) { 26 | if (odd_char != '\0') return "NO SOLUTION"; // More than one odd frequency 27 | odd_char = ch; // Store the character with odd frequency 28 | } 29 | 30 | first_half += string(count / 2, ch); // Append half of the characters 31 | } 32 | 33 | // Create the second half by mirroring the first half 34 | string second_half = first_half; 35 | reverse(second_half.begin(), second_half.end()); 36 | 37 | // Construct the palindrome 38 | string palindrome = first_half; 39 | if (odd_char != '\0') { 40 | palindrome += odd_char; // Add the odd character in the center if exists 41 | } 42 | palindrome += second_half; 43 | 44 | return palindrome; 45 | } 46 | 47 | int main() { 48 | string s; 49 | cin >> s; 50 | 51 | cout << constructPalindrome(s) << endl; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /intro/cses_2165.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // Recursive function to solve the Tower of Hanoi problem 7 | void solveHanoi(int n, int from, int to, int aux, vector>& moves) { 8 | if (n == 0) return; 9 | 10 | // Move n-1 disks from 'from' to 'aux', using 'to' as auxiliary 11 | solveHanoi(n - 1, from, aux, to, moves); 12 | 13 | // Move the nth disk from 'from' to 'to' 14 | moves.push_back({from, to}); 15 | 16 | // Move n-1 disks from 'aux' to 'to', using 'from' as auxiliary 17 | solveHanoi(n - 1, aux, to, from, moves); 18 | } 19 | 20 | int main() { 21 | int n; 22 | cin >> n; 23 | 24 | vector> moves; 25 | 26 | // Solve the Tower of Hanoi problem 27 | solveHanoi(n, 1, 3, 2, moves); 28 | 29 | // Output the number of moves 30 | cout << moves.size() << endl; 31 | 32 | // Output the moves 33 | for (const auto& move : moves) { 34 | cout << move.first << " " << move.second << endl; 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /intro/cses_2205.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Function to generate Gray code sequence of length n 8 | vector generateGrayCode(int n) { 9 | if (n == 0) { 10 | return {""}; 11 | } 12 | 13 | vector previousGrayCode = generateGrayCode(n - 1); 14 | vector grayCode; 15 | 16 | // Prefix with '0' 17 | for (const string& code : previousGrayCode) { 18 | grayCode.push_back("0" + code); 19 | } 20 | 21 | // Prefix with '1' and reverse the previousGrayCode 22 | for (auto it = previousGrayCode.rbegin(); it != previousGrayCode.rend(); ++it) { 23 | grayCode.push_back("1" + *it); 24 | } 25 | 26 | return grayCode; 27 | } 28 | 29 | int main() { 30 | int n; 31 | cin >> n; 32 | 33 | vector grayCode = generateGrayCode(n); 34 | 35 | for (const string& code : grayCode) { 36 | cout << code << endl; 37 | } 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /intro/cses_2220.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | const int MAX_DIGITS = 19; 11 | const int MOD = 1e9 + 7; 12 | 13 | // DP table 14 | long long dp[MAX_DIGITS][10][2]; 15 | 16 | // Function to count valid numbers up to the given limit 17 | long long countValidNumbers(const string &limit) { 18 | int n = limit.size(); 19 | memset(dp, -1, sizeof(dp)); 20 | 21 | // Use std::function to define a recursive lambda 22 | function dfs = [&](int pos, int lastDigit, bool isTight) -> long long { 23 | if (pos == n) return 1; // We've placed all digits successfully 24 | 25 | if (dp[pos][lastDigit][isTight] != -1) return dp[pos][lastDigit][isTight]; 26 | 27 | int maxDigit = isTight ? limit[pos] - '0' : 9; 28 | long long result = 0; 29 | 30 | for (int digit = 0; digit <= maxDigit; ++digit) { 31 | if (digit != lastDigit) { 32 | result += dfs(pos + 1, digit, isTight && (digit == maxDigit)); 33 | result %= MOD; 34 | } 35 | } 36 | 37 | return dp[pos][lastDigit][isTight] = result; 38 | }; 39 | 40 | return dfs(0, -1, true); 41 | } 42 | 43 | int main() { 44 | ios::sync_with_stdio(false); 45 | cin.tie(0); 46 | 47 | long long a, b; 48 | cin >> a >> b; 49 | 50 | string strA = to_string(a - 1); 51 | string strB = to_string(b); 52 | 53 | long long result = (countValidNumbers(strB) - countValidNumbers(strA) + MOD) % MOD; 54 | 55 | cout << result << endl; 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /intro/cses_2431.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | char findDigitAtPosition(long long k) { 9 | long long length = 1; // Length of the numbers (1, 2, 3, ...) 10 | long long count = 9; // Number of numbers with 'length' digits 11 | long long start = 1; // The smallest number with 'length' digits 12 | 13 | // Determine the length of the number containing the digit at position k 14 | while (k > length * count) { 15 | k -= length * count; 16 | length++; 17 | count *= 10; 18 | start *= 10; 19 | } 20 | 21 | // Find the exact number containing the k-th digit 22 | long long startNumber = start + (k - 1) / length; 23 | int digitIndex = (k - 1) % length; 24 | 25 | // Convert the number to a string and get the specific digit 26 | string numberStr = to_string(startNumber); 27 | return numberStr[digitIndex]; 28 | } 29 | 30 | int main() { 31 | ios::sync_with_stdio(false); 32 | cin.tie(nullptr); 33 | 34 | int q; 35 | cin >> q; 36 | 37 | vector queries(q); 38 | for (int i = 0; i < q; ++i) { 39 | cin >> queries[i]; 40 | } 41 | 42 | for (long long k : queries) { 43 | cout << findDigitAtPosition(k) << '\n'; 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /mathematics/cses1079.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1000000007; 5 | const int MAX = 1000000; 6 | 7 | std::vector fact(MAX + 1); 8 | std::vector inv_fact(MAX + 1); 9 | 10 | // Function to perform modular exponentiation 11 | long long mod_pow(long long base, long long exp, long long mod) { 12 | long long result = 1; 13 | while (exp > 0) { 14 | if (exp % 2 == 1) 15 | result = (result * base) % mod; 16 | base = (base * base) % mod; 17 | exp /= 2; 18 | } 19 | return result; 20 | } 21 | 22 | // Function to preprocess factorials and their inverses 23 | void preprocess() { 24 | fact[0] = fact[1] = 1; 25 | for (int i = 2; i <= MAX; ++i) { 26 | fact[i] = fact[i - 1] * i % MOD; 27 | } 28 | 29 | inv_fact[MAX] = mod_pow(fact[MAX], MOD - 2, MOD); // Fermat's little theorem 30 | for (int i = MAX - 1; i >= 0; --i) { 31 | inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD; 32 | } 33 | } 34 | 35 | // Function to calculate binomial coefficient C(a, b) % MOD 36 | long long binomial_coefficient(int a, int b) { 37 | if (b > a) return 0; 38 | return fact[a] * inv_fact[b] % MOD * inv_fact[a - b] % MOD; 39 | } 40 | 41 | int main() { 42 | preprocess(); 43 | 44 | int n; 45 | std::cin >> n; 46 | while (n--) { 47 | int a, b; 48 | std::cin >> a >> b; 49 | std::cout << binomial_coefficient(a, b) << "\n"; 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | // https://cses.fi/problemset/task/1716 56 | // Stars and Bars: The problem of distributing identical objects into distinct groups can be solved using the "stars and bars" technique. Imagine representing the m apples as stars (*) and using n-1 bars (|) to separate them into n groups (for the children). For example: 57 | // **|*|*** (2 apples for child 1, 1 for child 2, 3 for child 3) 58 | -------------------------------------------------------------------------------- /mathematics/cses1082.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | using ll = long long; 5 | const ll MOD = 1000000007; 6 | 7 | // Function to calculate (x^y) % p using Modular Exponentiation 8 | ll power(ll x, ll y, ll p) { 9 | ll res = 1; 10 | x = x % p; 11 | while (y > 0) { 12 | if (y & 1) 13 | res = (res * x) % p; 14 | y = y >> 1; 15 | x = (x * x) % p; 16 | } 17 | return (res + p) % p; 18 | } 19 | 20 | // Function to find modular inverse of x under modulo MOD 21 | ll mod_inv(ll x) { 22 | return power(x, MOD - 2, MOD); 23 | } 24 | 25 | // Function to calculate the sum from 1 to n modulo MOD 26 | ll sum(ll n) { 27 | return (((n % MOD) * ((n + 1) % MOD) % MOD) * mod_inv(2)) % MOD; 28 | } 29 | 30 | // Function to calculate the sum of divisors of all numbers from 1 to n 31 | ll divisorSum(ll n) { 32 | 33 | ll ans = 0; 34 | 35 | for (ll l = 1; l <= n;) { 36 | ll k = n / l; 37 | ll r = n / k; 38 | cout << "l: " << l << " r: " << r << " k: " << k << endl; 39 | k %= MOD; 40 | 41 | // For i=l to i=r, floor(n/i) will be k 42 | ans = (ans + ((sum(r) - sum(l - 1) + MOD) % MOD * k) % MOD) % MOD; 43 | l = r + 1; 44 | } 45 | 46 | return ans; 47 | } 48 | 49 | int main() { 50 | ll n; 51 | std::cin >> n; 52 | std::cout << divisorSum(n) << endl; 53 | return 0; 54 | } 55 | // g++ -std=c++14 -o a cses1082.cpp && ./a < a.in 56 | -------------------------------------------------------------------------------- /mathematics/cses1712.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | // Hàm tính a^b mod m bằng phương pháp Exponentiation by Squaring 7 | long long mod_exp(long long a, long long b, long long m) { 8 | long long result = 1; 9 | a %= m; // Tinh a mod m trước để tránh số quá lớn 10 | while (b > 0) { 11 | if (b % 2 == 1) { // Nếu b lẻ, nhân kết quả với a 12 | result = (result * a) % m; 13 | } 14 | a = (a * a) % m; // Cập nhật a = a^2 15 | b /= 2; // Chia b cho 2 16 | } 17 | return result; 18 | } 19 | 20 | // Hàm tính a^(b^c) mod m 21 | long long calculate(long long a, long long b, long long c, long long m) { 22 | if (b == 0) return 1; // Nếu b = 0, bất kỳ số mũ nào đều là 1 23 | // Tính b^c mod (m-1) vì theo định lý Euler, a^(b^c) % m = a^(b^c mod (m-1)) % m 24 | long long exp = mod_exp(b, c, m - 1); // b^c % (m-1) 25 | return mod_exp(a, exp, m); // a^exp % m 26 | } 27 | 28 | int main() { 29 | long long a, b, c; 30 | std::cin >> a >> b >> c; 31 | std::cout << calculate(a, b, c, MOD) << std::endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /mathematics/cses1715.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | const int MOD = 1e9 + 7; 7 | 8 | std::vector factorial; 9 | std::vector inverse_factorial; 10 | 11 | // Function to compute modular inverse using Fermat's Little Theorem 12 | long long mod_inv(long long a, int mod) { 13 | long long result = 1, exp = mod - 2; 14 | while (exp > 0) { 15 | if (exp % 2 == 1) result = result * a % mod; 16 | a = a * a % mod; 17 | exp /= 2; 18 | } 19 | return result; 20 | } 21 | 22 | // Function to precompute factorials and their modular inverses 23 | void precompute(int max_n) { 24 | factorial.resize(max_n + 1); 25 | inverse_factorial.resize(max_n + 1); 26 | factorial[0] = 1; 27 | for (int i = 1; i <= max_n; ++i) { 28 | factorial[i] = factorial[i - 1] * i % MOD; 29 | } 30 | inverse_factorial[max_n] = mod_inv(factorial[max_n], MOD); 31 | for (int i = max_n - 1; i >= 0; --i) { 32 | inverse_factorial[i] = inverse_factorial[i + 1] * (i + 1) % MOD; 33 | } 34 | } 35 | 36 | // Function to calculate the number of distinct permutations 37 | long long count_permutations(const std::string& s) { 38 | std::unordered_map freq; 39 | for (char c : s) { 40 | freq[c]++; 41 | } 42 | 43 | int n = s.size(); 44 | long long result = factorial[n]; 45 | 46 | for (auto& [character, count] : freq) { 47 | result = result * inverse_factorial[count] % MOD; 48 | } 49 | 50 | return result; 51 | } 52 | 53 | int main() { 54 | std::string s; 55 | std::cin >> s; 56 | 57 | int n = s.size(); 58 | 59 | // Precompute factorials and inverse factorials up to n 60 | precompute(n); 61 | 62 | // Compute the number of distinct permutations 63 | std::cout << count_permutations(s) << std::endl; 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /mathematics/cses1716.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | std::vector factorial; 7 | std::vector inverse_factorial; 8 | 9 | // Function to compute modular inverse using Fermat's Little Theorem 10 | long long mod_inv(long long a, int mod) { 11 | long long result = 1, exp = mod - 2; 12 | while (exp > 0) { 13 | if (exp % 2 == 1) result = result * a % mod; 14 | a = a * a % mod; 15 | exp /= 2; 16 | } 17 | return result; 18 | } 19 | 20 | // Function to precompute factorials and their modular inverses 21 | void precompute(int max_n) { 22 | factorial.resize(max_n + 1); 23 | inverse_factorial.resize(max_n + 1); 24 | factorial[0] = 1; 25 | for (int i = 1; i <= max_n; ++i) { 26 | factorial[i] = factorial[i - 1] * i % MOD; 27 | } 28 | inverse_factorial[max_n] = mod_inv(factorial[max_n], MOD); 29 | for (int i = max_n - 1; i >= 0; --i) { 30 | inverse_factorial[i] = inverse_factorial[i + 1] * (i + 1) % MOD; 31 | } 32 | } 33 | 34 | // Function to compute the binomial coefficient C(a, b) % MOD 35 | long long binomial_coefficient(int a, int b) { 36 | if (b > a || b < 0) return 0; 37 | return factorial[a] * inverse_factorial[b] % MOD * inverse_factorial[a - b] % MOD; 38 | } 39 | 40 | int main() { 41 | int n, m; 42 | std::cin >> n >> m; 43 | 44 | // Compute factorials and inverse factorials up to (n + m - 1) 45 | precompute(n + m - 1); 46 | 47 | // Compute the number of ways to distribute m apples among n children 48 | std::cout << binomial_coefficient(n + m - 1, m) << std::endl; 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /mathematics/cses1717.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | int countDerangements(int n) { 7 | // Base cases 8 | if (n == 1) return 0; 9 | if (n == 2) return 1; 10 | 11 | // Vector to store the number of derangements for each number up to n 12 | std::vector derangements(n + 1); 13 | derangements[0] = 1; // !0 = 1 14 | derangements[1] = 0; // !1 = 0 15 | 16 | for (int i = 2; i <= n; ++i) { 17 | derangements[i] = (i - 1) * (derangements[i - 1] + derangements[i - 2]) % MOD; 18 | } 19 | 20 | return derangements[n]; 21 | } 22 | 23 | int main() { 24 | int n; 25 | std::cin >> n; 26 | std::cout << countDerangements(n) << std::endl; 27 | return 0; 28 | } 29 | 30 | // The problem at hand involves calculating the number of ways to distribute gifts such that each child receives a gift brought by another child. This is a classic problem in combinatorics, specifically involving derangements (permutations where no element appears in its original position). 31 | 32 | // To solve this problem, we need to compute the number of derangements of \( n \) items, often denoted as \( !n \). The number of derangements can be computed using the following recursive formula: 33 | // \[ !n = (n - 1) \times (!(n - 1) + !(n - 2)) \] 34 | // with the base cases: 35 | // \[ !0 = 1 \] 36 | // \[ !1 = 0 \] 37 | 38 | // Given the constraint \( 1 \le n \le 10^6 \), we need an efficient way to compute derangements up to \( 10^6 \). This can be achieved using dynamic programming to avoid recalculating values multiple times. 39 | 40 | -------------------------------------------------------------------------------- /mathematics/cses1722.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | typedef std::vector> Matrix; 7 | 8 | // Function to multiply two 2x2 matrices with modulo operation 9 | Matrix multiply(const Matrix& a, const Matrix& b) { 10 | Matrix result(2, std::vector(2)); 11 | result[0][0] = (a[0][0] * b[0][0] + a[0][1] * b[1][0]) % MOD; 12 | result[0][1] = (a[0][0] * b[0][1] + a[0][1] * b[1][1]) % MOD; 13 | result[1][0] = (a[1][0] * b[0][0] + a[1][1] * b[1][0]) % MOD; 14 | result[1][1] = (a[1][0] * b[0][1] + a[1][1] * b[1][1]) % MOD; 15 | return result; 16 | } 17 | 18 | // Function to perform matrix exponentiation 19 | Matrix power(Matrix a, long long n) { 20 | Matrix result = {{1, 0}, {0, 1}}; // Identity matrix 21 | while (n > 0) { 22 | if (n % 2 == 1) { 23 | result = multiply(result, a); 24 | } 25 | a = multiply(a, a); 26 | n /= 2; 27 | } 28 | return result; 29 | } 30 | 31 | int main() { 32 | long long n; 33 | std::cin >> n; 34 | 35 | if (n == 0) { 36 | std::cout << 0 << std::endl; 37 | return 0; 38 | } 39 | if (n == 1) { 40 | std::cout << 1 << std::endl; 41 | return 0; 42 | } 43 | 44 | // Base transformation matrix 45 | Matrix F = {{1, 1}, {1, 0}}; 46 | 47 | // Compute F^n 48 | Matrix result = power(F, n - 1); 49 | 50 | // F_n is located at result[0][0] 51 | std::cout << result[0][0] << std::endl; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /mathematics/cses2064.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | std::vector factorial; 7 | std::vector inverse_factorial; 8 | 9 | long long mod_inv(long long a, int mod) { 10 | long long result = 1, exp = mod - 2; 11 | while (exp > 0) { 12 | if (exp % 2 == 1) result = result * a % mod; 13 | a = a * a % mod; 14 | exp /= 2; 15 | } 16 | return result; 17 | } 18 | 19 | void precompute(int max_n) { 20 | factorial.resize(max_n + 1); 21 | inverse_factorial.resize(max_n + 1); 22 | factorial[0] = 1; 23 | for (int i = 1; i <= max_n; ++i) { 24 | factorial[i] = factorial[i - 1] * i % MOD; 25 | } 26 | inverse_factorial[max_n] = mod_inv(factorial[max_n], MOD); 27 | for (int i = max_n - 1; i >= 0; --i) { 28 | inverse_factorial[i] = inverse_factorial[i + 1] * (i + 1) % MOD; 29 | } 30 | } 31 | 32 | long long catalan_number(int n) { 33 | if (n % 2 != 0) return 0; // If n is not even, no valid sequence. 34 | int k = n / 2; 35 | return factorial[2 * k] * inverse_factorial[k + 1] % MOD * inverse_factorial[k] % MOD; 36 | } 37 | 38 | int main() { 39 | int n; 40 | std::cin >> n; 41 | 42 | precompute(n); // Precompute factorials and inverse factorials up to n 43 | 44 | std::cout << catalan_number(n) << std::endl; 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /mathematics/cses2164.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int josephus_mth_removal(int n, int k, int m) { 5 | int index = 0; // Bắt đầu từ người đầu tiên 6 | for (int i = 1; i <= m; ++i) { 7 | index = (index + k - 1) % n; 8 | cout << i << " " << index << endl; 9 | if (i == m) { 10 | return index + 1; // Chuyển từ chỉ số bắt đầu từ 0 sang 1 11 | } 12 | --n; // Số lượng người giảm đi 1 13 | } 14 | return -1; // Trong trường hợp không tìm thấy 15 | } 16 | 17 | 18 | // const int MAX = 1e5 + 5; 19 | // int dp[MAX]; 20 | // // Function to find the k-th removed child 21 | 22 | int main() { 23 | ios_base::sync_with_stdio(false); 24 | cin.tie(NULL); 25 | 26 | int q; 27 | cin >> q; 28 | 29 | while (q--) { 30 | int n, k; 31 | cin >> n >> k; 32 | cout << n << " " << k << endl; 33 | cout << josephus_mth_removal(n, 2, k) << "\n"; 34 | } 35 | 36 | return 0; 37 | } 38 | // g++ -std=c++14 -o a cses2164.cpp && ./a < a.in -------------------------------------------------------------------------------- /mathematics/cses2189.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void determinePosition(long long x1, long long y1, long long x2, long long y2, long long x3, long long y3) { 5 | // Calculate the cross product 6 | long long cross_product = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); 7 | cout << '(' << x1 << ',' << y1 << ") -> (" << x2 << ',' << y2 << ") -> (" << x3 << ',' << y3 << ") -> " << cross_product << " \n "; 8 | // Determine the position of p3 with respect to the line 9 | if (cross_product > 0) { 10 | cout << "LEFT" << endl; 11 | } else if (cross_product < 0) { 12 | cout << "RIGHT" << endl; 13 | } else { 14 | cout << "TOUCH" << endl; 15 | } 16 | } 17 | 18 | int main() { 19 | int t; 20 | cin >> t; 21 | while (t--) { 22 | long long x1, y1, x2, y2, x3, y3; 23 | cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3; 24 | determinePosition(x1, y1, x2, y2, x3, y3); 25 | } 26 | return 0; 27 | } 28 | 29 | // g++ -std=c++14 -o a cses2189.cpp && ./a < a.in -------------------------------------------------------------------------------- /mathematics/cses2190.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Function to find the orientation of the ordered triplet (p, q, r) 5 | int orientation(long long x1, long long y1, long long x2, long long y2, long long x3, long long y3) { 6 | long long val = (y2 - y1) * (x3 - x2) - (x2 - x1) * (y3 - y2); 7 | if (val == 0) return 0; // collinear 8 | return (val > 0) ? 1 : 2; // clock or counterclockwise 9 | } 10 | 11 | // Function to check if point q lies on line segment pr 12 | bool isOnSegment(long long x1, long long y1, long long x2, long long y2, long long x3, long long y3) { 13 | if (x2 <= max(x1, x3) && x2 >= min(x1, x3) && y2 <= max(y1, y3) && y2 >= min(y1, y3)) return true; 14 | return false; 15 | } 16 | 17 | // Function to determine if the segments intersect 18 | bool doSegmentsIntersect(long long x1, long long y1, long long x2, long long y2, long long x3, long long y3, long long x4, long long y4) { 19 | int o1 = orientation(x1, y1, x2, y2, x3, y3); 20 | int o2 = orientation(x1, y1, x2, y2, x4, y4); 21 | int o3 = orientation(x3, y3, x4, y4, x1, y1); 22 | int o4 = orientation(x3, y3, x4, y4, x2, y2); 23 | 24 | // General case 25 | if (o1 != o2 && o3 != o4) return true; 26 | 27 | // Special cases 28 | if (o1 == 0 && isOnSegment(x1, y1, x3, y3, x2, y2)) return true; 29 | if (o2 == 0 && isOnSegment(x1, y1, x4, y4, x2, y2)) return true; 30 | if (o3 == 0 && isOnSegment(x3, y3, x1, y1, x4, y4)) return true; 31 | if (o4 == 0 && isOnSegment(x3, y3, x2, y2, x4, y4)) return true; 32 | 33 | return false; 34 | } 35 | 36 | int main() { 37 | int t; 38 | cin >> t; 39 | while (t--) { 40 | long long x1, y1, x2, y2, x3, y3, x4, y4; 41 | cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4; 42 | if (doSegmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) { 43 | cout << "YES" << endl; 44 | } else { 45 | cout << "NO" << endl; 46 | } 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /mathematics/cses2191.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Function to calculate the doubled area of the polygon using the Shoelace formula 8 | long long doubledArea(const vector>& vertices) { 9 | int n = vertices.size(); 10 | long long area = 0; 11 | 12 | for (int i = 0; i < n - 1; ++i) { 13 | area += vertices[i].first * vertices[i + 1].second; 14 | area -= vertices[i].second * vertices[i + 1].first; 15 | } 16 | 17 | // Add the last term (xn * y1 - yn * x1) 18 | area += vertices[n - 1].first * vertices[0].second; 19 | area -= vertices[n - 1].second * vertices[0].first; 20 | 21 | // Return the absolute value of the doubled area 22 | return abs(area); 23 | } 24 | 25 | int main() { 26 | int n; 27 | cin >> n; 28 | vector> vertices(n); 29 | 30 | for (int i = 0; i < n; ++i) { 31 | cin >> vertices[i].first >> vertices[i].second; 32 | } 33 | 34 | cout << doubledArea(vertices) << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /mathematics/cses_1081.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MAXX = 1e6 + 1; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | vector arr(n); 11 | vector freq(MAXX, 0); 12 | 13 | // Reading the input array and counting frequencies 14 | for (int i = 0; i < n; ++i) { 15 | cin >> arr[i]; 16 | freq[arr[i]]++; 17 | } 18 | 19 | // We will check each possible GCD from 1 to MAXX 20 | int result = 1; // The minimum possible GCD is 1 21 | for (int g = 1; g < MAXX; ++g) { 22 | int count = 0; 23 | // Count how many numbers are divisible by g 24 | for (int multiple = g; multiple < MAXX; multiple += g) { 25 | count += freq[multiple]; 26 | } 27 | // If there are at least two multiples of g, update the result 28 | if (count >= 2) { 29 | result = g; 30 | } 31 | } 32 | 33 | cout << result << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /mathematics/cses_1095.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | // Function to calculate a^b % MOD using binary exponentiation 7 | long long mod_pow(long long a, long long b, long long mod) { 8 | long long result = 1; 9 | a %= mod; 10 | while (b > 0) { 11 | if (b % 2 == 1) { 12 | result = (result * a) % mod; 13 | } 14 | a = (a * a) % mod; 15 | b /= 2; 16 | } 17 | return result; 18 | } 19 | 20 | int main() { 21 | ios::sync_with_stdio(false); 22 | cin.tie(nullptr); 23 | 24 | int n; 25 | cin >> n; 26 | 27 | while (n--) { 28 | long long a, b; 29 | cin >> a >> b; 30 | if (a == 0 && b == 0) { 31 | cout << 1 << "\n"; // 0^0 is considered 1 32 | } else { 33 | cout << mod_pow(a, b, MOD) << "\n"; 34 | } 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /mathematics/cses_1712.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MOD = 1e9 + 7; 5 | const int MOD_EXP = MOD - 1; // Fermat's Theorem requires using mod (MOD-1) for exponents 6 | 7 | // Function to calculate a^b % mod using binary exponentiation 8 | long long mod_pow(long long a, long long b, long long mod) { 9 | long long result = 1; 10 | a %= mod; 11 | while (b > 0) { 12 | if (b % 2 == 1) { 13 | result = (result * a) % mod; 14 | } 15 | a = (a * a) % mod; 16 | b /= 2; 17 | } 18 | return result; 19 | } 20 | 21 | // Function to calculate b^c % (MOD-1) for exponent reduction 22 | long long mod_exp_pow(long long b, long long c) { 23 | return mod_pow(b, c, MOD_EXP); 24 | } 25 | 26 | int main() { 27 | ios::sync_with_stdio(false); 28 | cin.tie(nullptr); 29 | 30 | int n; 31 | cin >> n; 32 | 33 | while (n--) { 34 | long long a, b, c; 35 | cin >> a >> b >> c; 36 | 37 | if (a == 0 && b == 0) { 38 | if (c == 0) { 39 | cout << 0 << "\n"; // Any 0^k is 0 40 | } else { 41 | cout << 1 << "\n"; // 0^0 is considered 1 42 | } 43 | 44 | } else if (a == 0) { 45 | cout << 0 << "\n"; // Any 0^k is 0 46 | } else { 47 | // First calculate b^c % (MOD-1) 48 | long long exp = mod_exp_pow(b, c); 49 | // Now calculate a^exp % MOD 50 | cout << mod_pow(a, exp, MOD) << "\n"; 51 | } 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /mathematics/cses_1713.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAXN = 1e6 + 1; 5 | int div_count[MAXN]; // div_count[i] will store the number of divisors of i 6 | 7 | // Precompute the number of divisors for every integer from 1 to MAXN-1 8 | void precompute_divisors() { 9 | // Initialize divisor counts to zero 10 | for (int i = 1; i < MAXN; i++) { 11 | for (int j = i; j < MAXN; j += i) { 12 | div_count[j]++; 13 | } 14 | } 15 | // Time complexity: O(N log N) N * (1 + 1/2 + 1/3 + ... + 1/N) = O(N log N) 16 | } 17 | 18 | int main() { 19 | ios::sync_with_stdio(false); 20 | cin.tie(nullptr); 21 | 22 | precompute_divisors(); // Precompute divisors count for all numbers up to MAXN-1 23 | 24 | int n; 25 | cin >> n; 26 | 27 | // Process each query 28 | while (n--) { 29 | int x; 30 | cin >> x; 31 | cout << div_count[x] << "\n"; // Output the number of divisors for x 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /mathematics/cses_1725.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAX_SUM = 600; // Since the maximum sum with 100 dice is 600 (100 * 6) 7 | 8 | int main() { 9 | int n, a, b; 10 | cin >> n >> a >> b; 11 | 12 | // dp[i][j] represents the probability of getting sum j with i dice rolls 13 | vector> dp(n + 1, vector(MAX_SUM + 1, 0.0)); 14 | 15 | // Base case: There's one way to get sum 0 with 0 dice rolls (probability = 1.0) 16 | dp[0][0] = 1.0; 17 | 18 | // Dynamic programming: fill the dp table 19 | for (int i = 1; i <= n; ++i) { 20 | for (int j = 0; j <= 6 * (i - 1); ++j) { 21 | for (int k = 1; k <= 6; ++k) { 22 | if (j + k <= MAX_SUM) { 23 | dp[i][j + k] += dp[i-1][j] / 6.0; 24 | } 25 | } 26 | } 27 | } 28 | 29 | // Sum the probabilities of achieving a sum between a and b with exactly n dice rolls 30 | double result = 0.0; 31 | for (int sum = a; sum <= b; ++sum) { 32 | result += dp[n][sum]; 33 | } 34 | 35 | // Output the result rounded to 6 decimal places 36 | cout << fixed << setprecision(6) << result << endl; 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /mathematics/cses_2185.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // for std::gcd 4 | using namespace std; 5 | typedef long long ll; 6 | 7 | ll gcd(ll a, ll b) { 8 | while (b != 0) { 9 | a %= b; 10 | swap(a, b); 11 | } 12 | return a; 13 | } 14 | 15 | // Function to calculate lcm of two numbers 16 | ll lcm(ll a, ll b) { 17 | return (a / gcd(a, b)) * b; 18 | } 19 | 20 | int main() { 21 | ll n; 22 | int k; 23 | cin >> n >> k; 24 | 25 | vector primes(k); 26 | for (int i = 0; i < k; ++i) { 27 | cin >> primes[i]; 28 | } 29 | 30 | ll result = 0; 31 | 32 | // Loop over all subsets of primes (2^k subsets) 33 | for (int mask = 1; mask < (1 << k); ++mask) { 34 | ll lcm_val = 1; 35 | int bits = 0; 36 | 37 | // For each bit in the mask, check which primes are selected 38 | for (int i = 0; i < k; ++i) { 39 | if (mask & (1 << i)) { 40 | lcm_val = lcm(lcm_val, primes[i]); 41 | // If LCM exceeds n, break early to avoid overflow 42 | if (lcm_val > n) break; 43 | bits++; 44 | } 45 | } 46 | 47 | if (lcm_val > n) continue; 48 | 49 | // Apply inclusion-exclusion principle 50 | ll multiples = n / lcm_val; 51 | if (bits % 2 == 1) { 52 | result += multiples; // Include 53 | } else { 54 | result -= multiples; // Exclude 55 | } 56 | } 57 | 58 | cout << result << endl; 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /mathematics/cses_2210.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MOD = 1e9 + 7; 5 | 6 | // Function to compute (base^exp) % mod using modular exponentiation 7 | long long mod_pow(long long base, long long exp, long long mod) { 8 | long long result = 1; 9 | while (exp > 0) { 10 | if (exp % 2 == 1) { 11 | result = (result * base) % mod; 12 | } 13 | base = (base * base) % mod; 14 | exp /= 2; 15 | } 16 | return result; 17 | } 18 | 19 | int main() { 20 | long long n; 21 | cin >> n; 22 | 23 | // Total number of grids without considering rotations is 2^(n^2) 24 | long long total_grids = mod_pow(2, n * n, MOD); 25 | 26 | // Now, we use Burnside's Lemma to calculate distinct grids. 27 | // For 0 degree rotation, all grids are unchanged. 28 | long long unchanged_0 = total_grids; 29 | 30 | // For 180 degree rotation, the grid must be symmetric around the center 31 | // If n is even, half the cells are free to choose, because each symmetric pair must be the same. 32 | // If n is odd, the center cell is independent, but all other cells are paired symmetrically. 33 | long long unchanged_180 = mod_pow(2, (n * n + 1) / 2, MOD); 34 | 35 | // For 90 and 270 degree rotations, the number of unchanged grids depends on the grid size. 36 | // If n % 2 != 0, no grid can remain unchanged under 90-degree rotation. 37 | // If n % 2 == 0, we have to calculate based on symmetric quadrants. 38 | 39 | long long unchanged_90 = 0; 40 | long long unchanged_270 = 0; 41 | 42 | if (n % 2 == 0) { 43 | unchanged_90 = mod_pow(2, (n / 2) * (n / 2), MOD); 44 | unchanged_270 = unchanged_90; 45 | } 46 | 47 | // Burnside's Lemma 48 | long long distinct_grids = (unchanged_0 + unchanged_180 + unchanged_90 + unchanged_270) % MOD; 49 | distinct_grids = (distinct_grids * mod_pow(4, MOD - 2, MOD)) % MOD; // Divide by 4 (modular inverse of 4) 50 | 51 | // Output the result 52 | cout << distinct_grids << endl; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /mathematics/cses_2417.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MAX = 1e6 + 5; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | 11 | vector arr(n); 12 | vector freq(MAX, 0); 13 | 14 | for (int i = 0; i < n; i++) { 15 | cin >> arr[i]; 16 | freq[arr[i]]++; 17 | } 18 | 19 | // Total number of pairs (n choose 2) 20 | long long totalPairs = 1LL * n * (n - 1) / 2; 21 | 22 | // Array to count how many numbers are divisible by i 23 | vector countDivisible(MAX, 0); 24 | 25 | // For each g, count how many numbers are divisible by g 26 | for (int g = 1; g < MAX; g++) { 27 | for (int multiple = g; multiple < MAX; multiple += g) { 28 | countDivisible[g] += freq[multiple]; 29 | } 30 | } 31 | 32 | // Now, calculate pairs that share a common divisor greater than 1 33 | long long nonCoprimePairs = 0; 34 | 35 | for (int g = 2; g < MAX; g++) { 36 | if (countDivisible[g] >= 2) { 37 | // Number of pairs with GCD >= g 38 | nonCoprimePairs += countDivisible[g] * (countDivisible[g] - 1) / 2; 39 | } 40 | } 41 | 42 | // The result is total pairs minus non-coprime pairs 43 | long long coprimePairs = totalPairs - nonCoprimePairs; 44 | 45 | cout << coprimePairs << endl; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /mathematics/ternary_578C.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef long double ld; // Use long double for higher precision 9 | 10 | const ld EPS = 1e-9; // Adjust precision 11 | 12 | // Function to calculate the maximum poorness for a given x 13 | ld calculate_weakness(const vector& a, ld x) { 14 | ld max_sum = 0, min_sum = 0; 15 | ld cur_max = 0, cur_min = 0; 16 | 17 | for (int i = 0; i < a.size(); i++) { 18 | ld val = a[i] - x; 19 | cur_max = max(val, cur_max + val); 20 | cur_min = min(val, cur_min + val); 21 | max_sum = max(max_sum, cur_max); 22 | min_sum = min(min_sum, cur_min); 23 | } 24 | 25 | return max(fabsl(max_sum), fabsl(min_sum)); // Use fabsl for long double 26 | } 27 | 28 | // Ternary search to find the optimal x 29 | ld ternary_search(const vector& a, ld low, ld high) { 30 | while (high - low > EPS) { 31 | ld mid1 = low + (high - low) / 3; 32 | ld mid2 = high - (high - low) / 3; 33 | 34 | ld weakness1 = calculate_weakness(a, mid1); 35 | ld weakness2 = calculate_weakness(a, mid2); 36 | 37 | if (weakness1 > weakness2) { 38 | low = mid1; 39 | } else { 40 | high = mid2; 41 | } 42 | } 43 | return low; 44 | } 45 | 46 | int main() { 47 | int n; 48 | cin >> n; 49 | 50 | vector a(n); 51 | for (int i = 0; i < n; i++) { 52 | cin >> a[i]; 53 | } 54 | 55 | // Ternary search between min(a) and max(a) 56 | // ld low = *min_element(a.begin(), a.end()); 57 | // ld high = *max_element(a.begin(), a.end()); 58 | ld low = -1e9, high = 1e9; // Set the range manually 59 | 60 | ld result = ternary_search(a, low, high); 61 | cout.precision(10); 62 | cout << fixed << calculate_weakness(a, result) << endl; // Print the optimal x directly 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /mathematics/ternary_building.cpp: -------------------------------------------------------------------------------- 1 | // https://www.spoj.com/problems/KOPC12A/ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | typedef long long ll; 10 | 11 | ll compute_cost(const vector& heights, const vector& costs, int target_height) { 12 | ll total_cost = 0; 13 | for (int i = 0; i < heights.size(); i++) { 14 | total_cost += abs(heights[i] - target_height) * (ll)costs[i]; 15 | } 16 | return total_cost; 17 | } 18 | 19 | ll ternary_search(const vector& heights, const vector& costs, int low, int high) { 20 | while (high - low > 2) { 21 | int mid1 = low + (high - low) / 3; 22 | int mid2 = high - (high - low) / 3; 23 | 24 | ll cost1 = compute_cost(heights, costs, mid1); 25 | ll cost2 = compute_cost(heights, costs, mid2); 26 | 27 | if (cost1 > cost2) { 28 | low = mid1; 29 | } else { 30 | high = mid2; 31 | } 32 | } 33 | 34 | // Brute force check the final few possible heights 35 | ll min_cost = compute_cost(heights, costs, low); 36 | for (int i = low + 1; i <= high; i++) { 37 | min_cost = min(min_cost, compute_cost(heights, costs, i)); 38 | } 39 | return min_cost; 40 | } 41 | 42 | int main() { 43 | int T; 44 | cin >> T; 45 | 46 | while (T--) { 47 | int n; 48 | cin >> n; 49 | 50 | vector heights(n); 51 | vector costs(n); 52 | 53 | for (int i = 0; i < n; i++) { 54 | cin >> heights[i]; 55 | } 56 | 57 | for (int i = 0; i < n; i++) { 58 | cin >> costs[i]; 59 | } 60 | 61 | // Apply ternary search between the minimum and maximum height in the input 62 | int min_height = *min_element(heights.begin(), heights.end()); 63 | int max_height = *max_element(heights.begin(), heights.end()); 64 | 65 | ll result = ternary_search(heights, costs, min_height, max_height); 66 | cout << result << endl; 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /mathematics/test.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def replace_text_in_file(file_path): 4 | with open(file_path, 'r') as file: 5 | content = file.read() 6 | 7 | # Use regular expression to find and replace the pattern 8 | modified_content = re.sub(r'\$ (\w+) \$', r'$\1$', content) 9 | 10 | with open(file_path, 'w') as file: 11 | file.write(modified_content) 12 | 13 | # Example usage 14 | file_path = '/Users/tuan/Desktop/house/cp-training/mathematics/cses1712-phi-euler.md' # Replace with the path to your text file 15 | replace_text_in_file(file_path) 16 | -------------------------------------------------------------------------------- /string-algorithms/1990C.cpp: -------------------------------------------------------------------------------- 1 | // https://codeforces.com/contest/1990/problem/C 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #define ll long long 9 | using namespace std; 10 | 11 | const int MAXN = (int)2e5 + 10; 12 | 13 | int n; 14 | int a[MAXN]; 15 | vector adj[MAXN]; 16 | 17 | set s; 18 | 19 | int main() { 20 | ios::sync_with_stdio(0); 21 | cin.tie(0); 22 | int nTest; 23 | cin >> nTest; 24 | 25 | while (nTest--) { 26 | 27 | cin >> n; 28 | vector a(n); 29 | for (int i = 0; i < n; i++) { 30 | cin >> a[i]; 31 | } 32 | ll ans = 0; 33 | for (int it = 0; it < 2; it++) { 34 | vector was(n + 1, false); 35 | 36 | int mx = 0; 37 | for (int i = 0; i < n; i++) { 38 | ans += a[i]; 39 | if (was[a[i]]) { 40 | mx = max(mx, a[i]); 41 | } 42 | 43 | was[a[i]] = true; 44 | a[i] = mx; 45 | cout << a[i] << " \n"[i == n - 1]; 46 | } 47 | 48 | } 49 | cout << ans << '\n'; 50 | for (int i = 0; i < n; i++) { 51 | ans += a[i] * 1LL * (n - i); 52 | cout << a[i] * 1LL * (n - i) << " \n"[i == n - 1]; 53 | } 54 | cout << ans << '\n'; 55 | } 56 | return 0; 57 | } 58 | // g++ -o a -std=c++11 1990C.cpp && ./a < a.in -------------------------------------------------------------------------------- /string-algorithms/cses_1110.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Function to find the lexicographically minimal rotation using Booth's algorithm 8 | string minimalRotation(const string& s) { 9 | string doubled = s + s; // Double the string 10 | int n = s.size(); 11 | vector f(n * 2, -1); // Failure function 12 | int k = 0; // Least rotation of string found so far 13 | 14 | for (int j = 1; j < doubled.size(); j++) { 15 | char sj = doubled[j]; 16 | int i = f[j - k - 1]; 17 | 18 | while (i != -1 && sj != doubled[k + i + 1]) { 19 | if (sj < doubled[k + i + 1]) { 20 | k = j - i - 1; 21 | } 22 | i = f[i]; 23 | } 24 | if (sj != doubled[k + i + 1]) { 25 | if (sj < doubled[k]) { 26 | k = j; 27 | } 28 | f[j - k] = -1; 29 | } else { 30 | f[j - k] = i + 1; 31 | } 32 | } 33 | 34 | return doubled.substr(k, n); // Return the minimal rotation 35 | } 36 | 37 | // Main function 38 | int main() { 39 | string s; 40 | cin >> s; 41 | 42 | string result = minimalRotation(s); 43 | cout << result << endl; 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /string-algorithms/cses_1111.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Function to transform the input string for Manacher's algorithm 8 | string preprocess(const string& s) { 9 | string result = "#"; 10 | for (char c : s) { 11 | result += c; 12 | result += "#"; 13 | } 14 | return result; 15 | } 16 | 17 | // Function to find the longest palindromic substring using Manacher's algorithm 18 | string longestPalindromicSubstring(const string& s) { 19 | string T = preprocess(s); 20 | int n = T.size(); 21 | vector P(n, 0); // Array to store the radius of palindromes 22 | int center = 0, right = 0; 23 | 24 | for (int i = 1; i < n - 1; i++) { 25 | if (i < right) { 26 | P[i] = min(right - i, P[2 * center - i]); // Use the mirror property 27 | } 28 | 29 | // Attempt to expand the palindrome centered at i 30 | while (T[i + P[i] + 1] == T[i - P[i] - 1]) { 31 | P[i]++; 32 | } 33 | 34 | // Update the center and right boundary if the palindrome extends past right 35 | if (i + P[i] > right) { 36 | center = i; 37 | right = i + P[i]; 38 | } 39 | } 40 | 41 | // Find the maximum radius and its center 42 | int maxLen = 0, centerIndex = 0; 43 | for (int i = 1; i < n - 1; i++) { 44 | if (P[i] > maxLen) { 45 | maxLen = P[i]; 46 | centerIndex = i; 47 | } 48 | } 49 | 50 | // Extract the longest palindrome 51 | // int start = (centerIndex - maxLen) / 2; // Calculate the start index in the original string 52 | int start = max(0, (centerIndex - maxLen) / 2); // Ensure start is non-negative 53 | 54 | return s.substr(start, maxLen); // Return the longest palindromic substring 55 | } 56 | 57 | // Main function 58 | int main() { 59 | string s; 60 | cin >> s; 61 | 62 | string result = longestPalindromicSubstring(s); 63 | cout << result << endl; 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /string-algorithms/cses_1112.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int MOD = 1e9 + 7; 8 | 9 | int main() { 10 | int n; // Length of the final string 11 | string pattern; // The pattern string 12 | cin >> n >> pattern; 13 | 14 | int m = pattern.size(); 15 | 16 | // If the pattern is longer than the string, it's impossible 17 | if (m > n) { 18 | cout << 0 << endl; 19 | return 0; 20 | } 21 | 22 | // Calculate 26^(n-m) mod MOD 23 | long long power = 1; 24 | for (int i = 0; i < n - m; ++i) { 25 | power = (power * 26) % MOD; 26 | } 27 | 28 | // Number of positions where the pattern can start 29 | long long positions = n - m + 1; 30 | 31 | // Total number of valid strings 32 | long long result = (positions * power) % MOD; 33 | 34 | cout << result << endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /string-algorithms/cses_1732.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // Function to compute the prefix function 6 | vector computePrefixFunction(const string& s) { 7 | int n = s.length(); 8 | vector pi(n); 9 | for (int i = 1; i < n; i++) { 10 | int j = pi[i - 1]; // length of previous longest border 11 | while (j > 0 && s[i] != s[j]) { 12 | j = pi[j - 1]; // fall back to the previous border 13 | } 14 | if (s[i] == s[j]) { 15 | j++; 16 | } 17 | pi[i] = j; // set the prefix function 18 | } 19 | return pi; 20 | } 21 | 22 | // Function to find all border lengths 23 | vector findBorderLengths(const string& s) { 24 | vector pi = computePrefixFunction(s); 25 | vector borders; 26 | 27 | int borderLength = pi.back(); // Length of the longest border 28 | while (borderLength > 0) { 29 | borders.push_back(borderLength); 30 | borderLength = pi[borderLength - 1]; // Move to the next border 31 | } 32 | 33 | // Reverse the borders to print in increasing order 34 | reverse(borders.begin(), borders.end()); 35 | return borders; 36 | } 37 | 38 | int main() { 39 | string s; 40 | cin >> s; 41 | 42 | vector borders = findBorderLengths(s); 43 | for (int length : borders) { 44 | cout << length << " "; 45 | } 46 | cout << endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /string-algorithms/cses_1733_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // Function to compute the prefix function 6 | vector computePrefixFunction(const string& s) { 7 | int n = s.length(); 8 | vector pi(n); 9 | for (int i = 1; i < n; i++) { 10 | int j = pi[i - 1]; // length of the previous longest border 11 | while (j > 0 && s[i] != s[j]) { 12 | j = pi[j - 1]; // fall back to the previous border 13 | } 14 | if (s[i] == s[j]) { 15 | j++; 16 | } 17 | pi[i] = j; // set the prefix function 18 | } 19 | return pi; 20 | } 21 | 22 | // Function to find all period lengths 23 | vector findPeriodLengths(const string& s) { 24 | int n = s.length(); 25 | vector pi = computePrefixFunction(s); 26 | vector periods; 27 | 28 | for (int i = 0; i < n; i++) { 29 | // Length of the period can be derived from pi 30 | int len = i + 1; // Length of the current substring s[0:i] 31 | int period = len - pi[i]; // Period length 32 | if (len % period == 0) { 33 | periods.push_back(len); 34 | } 35 | } 36 | 37 | return periods; 38 | } 39 | 40 | int main() { 41 | string s; 42 | cin >> s; 43 | 44 | vector periods = findPeriodLengths(s); 45 | for (int length : periods) { 46 | cout << length << " "; 47 | } 48 | cout << endl; 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /string-algorithms/cses_1753.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | // Function to build the LPS (Longest Prefix Suffix) array 7 | vector buildLPS(const string &pattern) { 8 | int m = pattern.length(); 9 | vector lps(m, 0); 10 | 11 | int length = 0; // Length of the previous longest prefix suffix 12 | int i = 1; // Start from the second character 13 | while (i < m) { 14 | if (pattern[i] == pattern[length]) { 15 | length++; 16 | lps[i] = length; 17 | i++; 18 | } else { 19 | if (length != 0) { 20 | // Don't increment i here 21 | length = lps[length - 1]; 22 | } else { 23 | lps[i] = 0; 24 | i++; 25 | } 26 | } 27 | } 28 | return lps; 29 | } 30 | 31 | // Function to count the occurrences of the pattern in the string 32 | int KMP(const string &text, const string &pattern) { 33 | int n = text.length(); 34 | int m = pattern.length(); 35 | 36 | // Build the LPS array for the pattern 37 | vector lps = buildLPS(pattern); 38 | 39 | int i = 0; // index for text 40 | int j = 0; // index for pattern 41 | int count = 0; // To count the occurrences 42 | 43 | while (i < n) { 44 | if (pattern[j] == text[i]) { 45 | i++; 46 | j++; 47 | } 48 | 49 | if (j == m) { 50 | count++; 51 | j = lps[j - 1]; 52 | } else if (i < n && pattern[j] != text[i]) { 53 | if (j != 0) { 54 | j = lps[j - 1]; 55 | } else { 56 | i++; 57 | } 58 | } 59 | } 60 | 61 | return count; 62 | } 63 | 64 | int main() { 65 | string text, pattern; 66 | cin >> text >> pattern; 67 | 68 | // Count the number of occurrences of the pattern in the text 69 | int result = KMP(text, pattern); 70 | 71 | // Output the result 72 | cout << result << endl; 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /training-topic/code-sub-task/sumn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtuann/competitive-programming-101/6d2aa5ea11b9df761a91c996358454760d1b9292/training-topic/code-sub-task/sumn -------------------------------------------------------------------------------- /training-topic/code-sub-task/sumn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | bool is_subtask1(long long n) { 7 | return n <= 10; 8 | } 9 | 10 | bool is_subtask2(long long n) { 11 | return n <= 1000; 12 | } 13 | 14 | bool is_subtask3(long long n) { 15 | return n <= 1000000; 16 | } 17 | 18 | bool is_subtask4(long long n) { 19 | return n <= 1000000000; 20 | } 21 | 22 | namespace subtask1 { 23 | long long sum(long long n) { 24 | return n * (n + 1) / 2; 25 | } 26 | }; 27 | 28 | namespace subtask2 { 29 | long long sum(long long n) { 30 | return n * (n + 1) / 2; 31 | } 32 | }; 33 | 34 | namespace subtask3 { 35 | long long sum(long long n) { 36 | return n * (n + 1) / 2; 37 | } 38 | }; 39 | 40 | namespace subtask4 { 41 | long long sum(long long n) { 42 | return n * (n + 1) / 2; 43 | } 44 | }; 45 | 46 | int main() { 47 | long long n; 48 | cin >> n; 49 | 50 | if (is_subtask1(n)) return cout << subtask1::sum(n) << endl, 0; 51 | if (is_subtask2(n)) return cout << subtask2::sum(n) << endl, 0; 52 | if (is_subtask3(n)) return cout << subtask3::sum(n) << endl, 0; 53 | if (is_subtask4(n)) return cout << subtask4::sum(n) << endl, 0; 54 | 55 | return 0; 56 | } 57 | 58 | // g++ -std=c++14 -O2 -Wall -Wextra sumn.cpp -o sumn && ./sumn -------------------------------------------------------------------------------- /training-topic/product-gen/problem_solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | freopen("product.inp", "r", stdin); 7 | freopen("product.out", "w", stdout); 8 | 9 | long long a, b; 10 | cin >> a >> b; 11 | cout << a * b << endl; 12 | return 0; 13 | } -------------------------------------------------------------------------------- /training-topic/product-gen/product_check.sh: -------------------------------------------------------------------------------- 1 | ./product_gen.exe 2 | ./product_slow.exe 3 | ./problem_solution.exe 4 | diff product.ans product.out -------------------------------------------------------------------------------- /training-topic/product-gen/product_gen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // Function to generate a random number in a given range [min, max] 9 | long long randomNumber(long long min, long long max) { 10 | long long res = 0; 11 | for (int i = 0; i < 4; ++i) 12 | res = (res << 15) + (rand() & 0x7FFF); 13 | return min + res % (max - min + 1); 14 | } 15 | 16 | int main() { 17 | freopen("product.inp", "w", stdout); 18 | srand(time(nullptr)); // Seed for random number generation 19 | 20 | // random a, b in range [1, 10^9] with 4 subtask [1, 10], [1, 1e3], [1, 1e6], [1, 1e9] 21 | long long type = randomNumber(1, 4); 22 | long long a, b; 23 | if (type == 1) { 24 | a = randomNumber(1, 10); 25 | b = randomNumber(1, 10); 26 | } else if (type == 2) { 27 | a = randomNumber(1, 1000); 28 | b = randomNumber(1, 1000); 29 | } else if (type == 3) { 30 | a = randomNumber(1, 1000000); 31 | b = randomNumber(1, 1000000); 32 | } else { 33 | a = randomNumber(1, 1000000000); 34 | b = randomNumber(1, 1000000000); 35 | } 36 | cout << a << " " << b << endl; 37 | cerr << a << " " << b << endl; 38 | return 0; 39 | } -------------------------------------------------------------------------------- /training-topic/product-gen/product_slow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | freopen("product.inp", "r", stdin); 7 | freopen("product.ans", "w", stdout); 8 | 9 | long long a, b; 10 | cin >> a >> b; 11 | long long sum = 0; 12 | for (int i = 0; i < a; ++i) { 13 | sum += b; 14 | } 15 | cout << sum << endl; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtuann/competitive-programming-101/6d2aa5ea11b9df761a91c996358454760d1b9292/training-topic/sorting-and-searching/a -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/built-in.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int a[] = {1, 2, 2, 4, 4, 4, 5}; 7 | int n = sizeof(a) / sizeof(a[0]); 8 | int x = 3; 9 | int lower = lower_bound(a, a + n, x) - a; 10 | x = 4; 11 | int upper = upper_bound(a, a + n, x) - a; 12 | cout << lower << " " << upper << endl; // Output: 3 3 13 | return 0; 14 | } 15 | // g++ built-in.cpp -o a && ./a -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1073.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | vector cubes(n); 11 | 12 | for (int i = 0; i < n; ++i) { 13 | cin >> cubes[i]; 14 | } 15 | 16 | multiset towers; 17 | 18 | for (int cube : cubes) { 19 | auto it = towers.upper_bound(cube); 20 | if (it != towers.end()) { 21 | towers.erase(it); 22 | } 23 | towers.insert(cube); 24 | } 25 | 26 | cout << towers.size() << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1074.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | ios::sync_with_stdio(false); 8 | cin.tie(nullptr); 9 | 10 | int n; 11 | cin >> n; 12 | vector sticks(n); 13 | 14 | for (int i = 0; i < n; ++i) { 15 | cin >> sticks[i]; 16 | } 17 | 18 | // Sort the stick lengths to find the median 19 | sort(sticks.begin(), sticks.end()); 20 | 21 | // Find the median 22 | int median = sticks[n / 2]; 23 | 24 | // Calculate the total cost to make all sticks equal to the median 25 | long long total_cost = 0; 26 | for (int i = 0; i < n; ++i) { 27 | total_cost += abs(sticks[i] - median); 28 | } 29 | 30 | cout << total_cost << endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1084.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int MAXN = 2e5 + 10; 8 | int n, m, k; 9 | int applicants[MAXN]; 10 | int apartments[MAXN]; 11 | 12 | int main() { 13 | ios::sync_with_stdio(false); 14 | cin.tie(nullptr); 15 | 16 | cin >> n >> m >> k; 17 | 18 | for (int i = 0; i < n; ++i) { 19 | cin >> applicants[i]; 20 | } 21 | 22 | for (int i = 0; i < m; ++i) { 23 | cin >> apartments[i]; 24 | } 25 | 26 | // Sort both the applicants and the apartments 27 | sort(applicants, applicants + n); 28 | sort(apartments, apartments + m); 29 | 30 | int i = 0; // Index for applicants 31 | int j = 0; // Index for apartments 32 | int count = 0; 33 | 34 | while (i < n && j < m) { 35 | if (apartments[j] < applicants[i] - k) { 36 | // Apartment too small, move to the next apartment 37 | j++; 38 | } else if (apartments[j] > applicants[i] + k) { 39 | // Apartment too big, move to the next applicant 40 | i++; 41 | } else { 42 | // Apartment fits within the acceptable range 43 | count++; 44 | i++; 45 | j++; 46 | } 47 | } 48 | 49 | cout << count << endl; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1085.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | bool canDivide(const vector& arr, int k, long long max_sum) { 9 | long long current_sum = 0; 10 | int subarray_count = 1; // Start with one subarray 11 | 12 | for (int value : arr) { 13 | if (current_sum + value > max_sum) { 14 | // Need to start a new subarray 15 | ++subarray_count; 16 | current_sum = value; 17 | 18 | if (subarray_count > k) { 19 | return false; // More subarrays than allowed 20 | } 21 | } else { 22 | current_sum += value; 23 | } 24 | } 25 | return true; 26 | } 27 | 28 | int main() { 29 | int n, k; 30 | cin >> n >> k; 31 | 32 | vector arr(n); 33 | for (int i = 0; i < n; ++i) { 34 | cin >> arr[i]; 35 | } 36 | 37 | long long left = *max_element(arr.begin(), arr.end()); 38 | long long right = accumulate(arr.begin(), arr.end(), 0LL); 39 | long long result = right; 40 | 41 | while (left <= right) { 42 | long long mid = left + (right - left) / 2; 43 | 44 | if (canDivide(arr, k, mid)) { 45 | result = mid; 46 | right = mid - 1; 47 | } else { 48 | left = mid + 1; 49 | } 50 | } 51 | 52 | cout << result << endl; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1090.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int MAX_N = 10 + 200000; // maximum number of children 6 | 7 | int weights[MAX_N]; 8 | 9 | int main() { 10 | ios::sync_with_stdio(false); 11 | cin.tie(nullptr); 12 | 13 | int n, x; 14 | cin >> n >> x; 15 | 16 | for (int i = 0; i < n; ++i) { 17 | cin >> weights[i]; 18 | } 19 | 20 | // Sort the weights of the children 21 | sort(weights, weights + n); 22 | 23 | int i = 0; // Index for the lightest child 24 | int j = n - 1; // Index for the heaviest child 25 | int gondolas = 0; 26 | 27 | while (i <= j) { 28 | if (weights[i] + weights[j] <= x) { 29 | // If the lightest and the heaviest child can share a gondola 30 | i++; 31 | } 32 | // Move to the next heaviest child 33 | j--; 34 | // One gondola used 35 | gondolas++; 36 | } 37 | 38 | cout << gondolas << endl; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1091.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAXN = 2e5 + 10; 7 | int n, m; 8 | multiset ticket_prices; 9 | 10 | int main() { 11 | ios::sync_with_stdio(false); 12 | cin.tie(nullptr); 13 | 14 | int n, m; 15 | cin >> n >> m; 16 | 17 | // Read the ticket prices 18 | for (int i = 0; i < n; ++i) { 19 | int price; 20 | cin >> price; 21 | ticket_prices.insert(price); 22 | } 23 | 24 | // Read the maximum prices customers are willing to pay 25 | for (int i = 0; i < m; ++i) { 26 | int max_price; 27 | cin >> max_price; 28 | auto it = ticket_prices.upper_bound(max_price); 29 | if (it == ticket_prices.begin()) { 30 | // No ticket can be assigned to this customer 31 | cout << -1 << "\n"; 32 | } else { 33 | // A suitable ticket is found 34 | --it; // Move to the largest element that is <= max_prices[i] 35 | cout << *it << "\n"; 36 | ticket_prices.erase(it); // Remove this ticket from the set 37 | } 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1163.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | ios::sync_with_stdio(0); 10 | cin.tie(0); 11 | int x, n; 12 | cin >> x >> n; 13 | vector positions(n); 14 | 15 | for (int i = 0; i < n; ++i) { 16 | cin >> positions[i]; 17 | } 18 | 19 | set lights; 20 | multiset segments; 21 | 22 | // Initially, we have one segment from 0 to x 23 | lights.insert(0); 24 | lights.insert(x); 25 | segments.insert(x); 26 | 27 | for (int p : positions) { 28 | auto it = lights.lower_bound(p); 29 | int right = *it; 30 | int left = *(--it); 31 | 32 | // Remove the current segment 33 | segments.erase(segments.find(right - left)); 34 | 35 | // Insert new segments 36 | segments.insert(p - left); 37 | segments.insert(right - p); 38 | 39 | // Insert the new light position 40 | lights.insert(p); 41 | 42 | // Output the maximum segment length 43 | cout << *segments.rbegin() << " "; 44 | } 45 | 46 | cout << endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1164.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct Event { 9 | int time; 10 | int type; // +1 for arrival, -1 for departure 11 | int index; 12 | }; 13 | 14 | int main() { 15 | int n; 16 | cin >> n; 17 | 18 | vector> customers(n); 19 | vector events; 20 | for (int i = 0; i < n; ++i) { 21 | int a, b; 22 | cin >> a >> b; 23 | customers[i] = {a, b}; 24 | events.push_back({a, +1, i}); // arrival 25 | events.push_back({b + 1, -1, i}); // departure (b + 1) 26 | } 27 | 28 | sort(events.begin(), events.end(), [](const Event &e1, const Event &e2) { 29 | if (e1.time == e2.time) return e1.type < e2.type; 30 | return e1.time < e2.time; 31 | }); 32 | 33 | int max_rooms = 0; 34 | int current_rooms = 0; 35 | vector room_assignment(n); 36 | priority_queue, greater> available_rooms; 37 | 38 | for (const auto& event : events) { 39 | if (event.type == +1) { // arrival 40 | current_rooms++; 41 | if (available_rooms.empty()) { 42 | max_rooms++; 43 | room_assignment[event.index] = max_rooms; 44 | } else { 45 | int room = available_rooms.top(); 46 | available_rooms.pop(); 47 | room_assignment[event.index] = room; 48 | } 49 | } else { // departure 50 | current_rooms--; 51 | available_rooms.push(room_assignment[event.index]); 52 | } 53 | } 54 | 55 | cout << max_rooms << endl; 56 | for (int i = 0; i < n; ++i) { 57 | cout << room_assignment[i] << " "; 58 | } 59 | cout << endl; 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1619.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAXN = 2e5 + 10; 7 | 8 | struct Event { 9 | int time; 10 | int type; // +1 for arrival, -1 for departure 11 | }; 12 | 13 | // Custom comparator to sort events 14 | bool compareEvents(const Event &e1, const Event &e2) { 15 | if (e1.time == e2.time) { 16 | return e1.type < e2.type; // Prioritize departures over arrivals if times are the same 17 | } 18 | return e1.time < e2.time; 19 | } 20 | 21 | int n; 22 | Event events[2 * MAXN]; 23 | 24 | int main() { 25 | ios::sync_with_stdio(false); 26 | cin.tie(nullptr); 27 | 28 | int n; 29 | cin >> n; 30 | int nn = 0; 31 | // Read the arrival and departure times 32 | for (int i = 0; i < n; ++i) { 33 | int arrival, departure; 34 | cin >> arrival >> departure; 35 | events[nn++] = {arrival, 1}; // Arrival event 36 | events[nn++] = {departure, -1}; // Departure event 37 | } 38 | 39 | // Sort the events 40 | sort(events, events + nn, compareEvents); 41 | 42 | int current_customers = 0; 43 | int max_customers = 0; 44 | 45 | // Process the events 46 | for (int i = 0; i < nn; ++i) { 47 | Event event = events[i]; 48 | current_customers += event.type; 49 | if (current_customers > max_customers) { 50 | max_customers = current_customers; 51 | } 52 | } 53 | 54 | cout << max_customers << endl; 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1620.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | long long n, t; 7 | 8 | bool canProduceProductsInTime(const vector& machines, long long n, long long t, long long time) { 9 | long long totalProducts = 0; 10 | for (long long machine : machines) { 11 | totalProducts += time / machine; 12 | if (totalProducts >= t) { 13 | return true; 14 | } 15 | } 16 | return false; 17 | } 18 | 19 | long long findMinimumTime(vector& machines, long long n, long long t) { 20 | long long left = 1; 21 | long long right = *max_element(machines.begin(), machines.end()) * t; 22 | long long result = right; 23 | 24 | while (left <= right) { 25 | long long mid = left + (right - left) / 2; 26 | if (canProduceProductsInTime(machines, n, t, mid)) { 27 | result = mid; 28 | right = mid - 1; 29 | } else { 30 | left = mid + 1; 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | 37 | int main() { 38 | 39 | cin >> n >> t; 40 | vector machines(n); 41 | for (long long i = 0; i < n; ++i) { 42 | cin >> machines[i]; 43 | } 44 | 45 | cout << findMinimumTime(machines, n, t) << endl; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1621.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int MAXN = 2e5 + 10; 8 | 9 | int n; 10 | int values[MAXN]; 11 | 12 | int main() { 13 | ios::sync_with_stdio(false); 14 | cin.tie(nullptr); 15 | 16 | int n; 17 | cin >> n; 18 | 19 | for (int i = 0; i < n; ++i) { 20 | cin >> values[i]; 21 | } 22 | 23 | // Sort the array 24 | sort(values, values + n); 25 | 26 | // Count distinct values 27 | int distinct_count = 1; // At least one distinct value if n > 0 28 | for (int i = 1; i < n; ++i) { 29 | if (values[i] != values[i-1]) { 30 | distinct_count++; 31 | } 32 | } 33 | 34 | cout << distinct_count << endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1629.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Movie { 7 | int start; 8 | int end; 9 | }; 10 | 11 | // Comparator to sort movies by end time 12 | bool compareMovies(const Movie &m1, const Movie &m2) { 13 | return m1.end < m2.end; 14 | } 15 | 16 | int main() { 17 | ios::sync_with_stdio(false); 18 | cin.tie(nullptr); 19 | 20 | int n; 21 | cin >> n; 22 | 23 | vector movies(n); 24 | 25 | // Read the start and end times of each movie 26 | for (int i = 0; i < n; ++i) { 27 | cin >> movies[i].start >> movies[i].end; 28 | } 29 | 30 | // Sort the movies by their end times 31 | sort(movies.begin(), movies.end(), compareMovies); 32 | 33 | int count = 0; 34 | int last_end_time = 0; 35 | 36 | // Iterate through the sorted movies and select non-overlapping movies 37 | for (const auto &movie : movies) { 38 | if (movie.start >= last_end_time) { 39 | count++; 40 | last_end_time = movie.end; 41 | } 42 | } 43 | 44 | cout << count << endl; 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1630.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | 11 | vector> tasks(n); 12 | for (int i = 0; i < n; ++i) { 13 | cin >> tasks[i].first >> tasks[i].second; 14 | } 15 | 16 | // Sort tasks by their durations 17 | sort(tasks.begin(), tasks.end()); 18 | 19 | long long totalReward = 0; 20 | long long currentTime = 0; 21 | 22 | for (int i = 0; i < n; ++i) { 23 | int duration = tasks[i].first; 24 | int deadline = tasks[i].second; 25 | 26 | currentTime += duration; 27 | totalReward += (deadline - currentTime); 28 | } 29 | 30 | cout << totalReward << endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1631.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | vector t(n); 11 | for (int i = 0; i < n; ++i) { 12 | cin >> t[i]; 13 | } 14 | 15 | // Sort the times in descending order 16 | sort(t.rbegin(), t.rend()); 17 | 18 | long long A = 0, B = 0; 19 | 20 | for (int i = 0; i < n; ++i) { 21 | if (A <= B) { 22 | A += t[i]; 23 | } else { 24 | B += t[i]; 25 | } 26 | } 27 | 28 | cout << max(A, B) << endl; 29 | 30 | return 0; 31 | } 32 | // g++ -std=c++14 -O2 -Wall cses_1631.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1632.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct Movie { 9 | int start, end; 10 | bool operator<(const Movie& other) const { 11 | return end < other.end; // Sorting by ending time 12 | } 13 | }; 14 | 15 | int main() { 16 | ios::sync_with_stdio(false); 17 | cin.tie(0); 18 | 19 | int n, k; 20 | cin >> n >> k; 21 | 22 | vector movies(n); 23 | for (int i = 0; i < n; ++i) { 24 | cin >> movies[i].start >> movies[i].end; 25 | } 26 | 27 | // Sort movies by their ending time 28 | sort(movies.begin(), movies.end()); 29 | 30 | // Min-heap to keep track of the end times of the movies being watched by each member 31 | priority_queue, greater> endTimes; 32 | 33 | int maxMovies = 0; 34 | 35 | for (const Movie& movie : movies) { 36 | cout << movie.start << " " << movie.end << endl; 37 | // Assign the movie to a member (either a free one or a new member if less than k members are using the heap) 38 | if (endTimes.size() < k) { 39 | cout << "Watching movie: " << movie.start << " " << movie.end << endl; 40 | ++maxMovies; 41 | while (!endTimes.empty() && endTimes.top() <= movie.start) { 42 | // Reuse the member who has finished watching their movie 43 | endTimes.pop(); 44 | } 45 | endTimes.push(movie.end); 46 | } 47 | // Update the end time for the member watching this movie 48 | 49 | } 50 | 51 | cout << maxMovies << endl; 52 | 53 | return 0; 54 | } 55 | // g++ -std=c++14 -O2 -Wall cses_1632.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1640.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct custom_hash { 8 | static uint64_t splitmix64(uint64_t x) { 9 | // http://xorshift.di.unimi.it/splitmix64.c 10 | x += 0x9e3779b97f4a7c15; 11 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 12 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 13 | return x ^ (x >> 31); 14 | } 15 | 16 | size_t operator()(uint64_t x) const { 17 | static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); 18 | return splitmix64(x + FIXED_RANDOM); 19 | } 20 | }; 21 | 22 | int main() { 23 | ios::sync_with_stdio(false); 24 | cin.tie(nullptr); 25 | 26 | int n, x; 27 | cin >> n >> x; 28 | 29 | vector a(n); 30 | unordered_map value_to_index; 31 | 32 | for (int i = 0; i < n; ++i) { 33 | cin >> a[i]; 34 | } 35 | 36 | for (int i = 0; i < n; ++i) { 37 | int complement = x - a[i]; 38 | if (value_to_index.find(complement) != value_to_index.end()) { 39 | cout << value_to_index[complement] + 1 << " " << i + 1 << "\n"; 40 | return 0; 41 | } 42 | value_to_index[a[i]] = i; 43 | } 44 | 45 | cout << "IMPOSSIBLE\n"; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1641.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | long long x; 10 | cin >> n >> x; 11 | vector> a(n); 12 | 13 | for (int i = 0; i < n; ++i) { 14 | cin >> a[i].first; 15 | a[i].second = i + 1; // store original positions 16 | } 17 | 18 | // Sort array based on the values 19 | sort(a.begin(), a.end()); 20 | 21 | for (int i = 0; i < n - 2; ++i) { 22 | int left = i + 1; 23 | int right = n - 1; 24 | 25 | while (left < right) { 26 | long long sum = a[i].first + a[left].first + a[right].first; 27 | if (sum == x) { 28 | cout << a[i].second << " " << a[left].second << " " << a[right].second << endl; 29 | return 0; 30 | } else if (sum < x) { 31 | ++left; 32 | } else { 33 | --right; 34 | } 35 | } 36 | } 37 | 38 | cout << "IMPOSSIBLE" << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1642.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | int n, x; 10 | cin >> n >> x; 11 | 12 | vector arr(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> arr[i]; 15 | } 16 | 17 | unordered_map>> pair_sum_map; 18 | 19 | // Store all pairs and their indices 20 | for (int i = 0; i < n; ++i) { 21 | for (int j = i + 1; j < n; ++j) { 22 | int sum = arr[i] + arr[j]; 23 | pair_sum_map[sum].emplace_back(i, j); 24 | } 25 | } 26 | 27 | // Check for valid quadruples 28 | for (int i = 0; i < n; ++i) { 29 | for (int j = i + 1; j < n; ++j) { 30 | int sum = arr[i] + arr[j]; 31 | int complement = x - sum; 32 | 33 | if (pair_sum_map.find(complement) != pair_sum_map.end()) { 34 | for (auto& [p1, p2] : pair_sum_map[complement]) { 35 | if (p1 != i && p1 != j && p2 != i && p2 != j) { 36 | cout << p1 + 1 << " " << p2 + 1 << " " << i + 1 << " " << j + 1 << endl; 37 | return 0; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | cout << "IMPOSSIBLE" << endl; 45 | return 0; 46 | } 47 | 48 | 49 | // g++ -std=c++17 -o a cses_1642.cpp && ./a < a.in 50 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1643.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | ios::sync_with_stdio(false); 8 | cin.tie(nullptr); 9 | 10 | int n; 11 | cin >> n; 12 | 13 | vector array(n); 14 | for (int i = 0; i < n; ++i) { 15 | cin >> array[i]; 16 | } 17 | 18 | long long current_sum = array[0]; 19 | long long max_sum = array[0]; 20 | 21 | for (int i = 1; i < n; ++i) { 22 | current_sum = max(array[i], current_sum + array[i]); 23 | max_sum = max(max_sum, current_sum); 24 | } 25 | 26 | cout << max_sum << endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1644.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main() { 10 | ios::sync_with_stdio(false); 11 | cin.tie(0); 12 | 13 | int n, a, b; 14 | cin >> n >> a >> b; 15 | 16 | vector arr(n); 17 | for (int i = 0; i < n; ++i) { 18 | cin >> arr[i]; 19 | } 20 | 21 | // Compute prefix sums 22 | vector prefix(n + 1, 0); 23 | for (int i = 0; i < n; ++i) { 24 | prefix[i + 1] = prefix[i] + arr[i]; 25 | } 26 | 27 | // Deque to store indices of prefix sums 28 | deque dq; 29 | long long max_sum = LLONG_MIN; 30 | 31 | for (int i = 0; i <= n; ++i) { 32 | // Maintain the deque so that the prefix sums are in increasing order 33 | while (!dq.empty() && dq.front() < i - b) { 34 | dq.pop_front(); 35 | } 36 | // Compute the max sum of subarrays with length in the range [a, b] 37 | if (i >= a) { 38 | max_sum = max(max_sum, prefix[i] - prefix[dq.front()]); 39 | } 40 | // Maintain the deque to have the smallest prefix sum at the back 41 | while (!dq.empty() && prefix[dq.back()] >= prefix[i]) { 42 | dq.pop_back(); 43 | } 44 | dq.push_back(i); 45 | } 46 | 47 | cout << max_sum << endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1645.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | 11 | vector arr(n); 12 | for (int i = 0; i < n; ++i) { 13 | cin >> arr[i]; 14 | } 15 | 16 | vector result(n); 17 | stack s; 18 | 19 | for (int i = 0; i < n; ++i) { 20 | // Pop elements from the stack until we find a smaller element or the stack is empty 21 | while (!s.empty() && arr[s.top()] >= arr[i]) { 22 | s.pop(); 23 | } 24 | // If stack is not empty, the top of the stack is the nearest smaller element 25 | if (!s.empty()) { 26 | result[i] = s.top() + 1; // Convert to 1-based index 27 | } else { 28 | result[i] = 0; 29 | } 30 | // Push the current index onto the stack 31 | s.push(i); 32 | } 33 | 34 | // Print the result 35 | for (int i = 0; i < n; ++i) { 36 | cout << result[i] << " "; 37 | } 38 | cout << endl; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1660.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | int n, x; 8 | cin >> n >> x; 9 | 10 | vector arr(n); 11 | for (int i = 0; i < n; ++i) { 12 | cin >> arr[i]; 13 | } 14 | 15 | int count = 0; 16 | int current_sum = 0; 17 | int start = 0; 18 | 19 | for (int end = 0; end < n; ++end) { 20 | current_sum += arr[end]; 21 | 22 | // Shrink the window from the left if the current_sum is greater than x 23 | while (current_sum > x && start <= end) { 24 | current_sum -= arr[start]; 25 | ++start; 26 | } 27 | 28 | // Check if the current_sum is exactly x 29 | if (current_sum == x) { 30 | ++count; 31 | } 32 | } 33 | 34 | cout << count << endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1661.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | struct custom_hash { 8 | static uint64_t splitmix64(uint64_t x) { 9 | // http://xorshift.di.unimi.it/splitmix64.c 10 | x += 0x9e3779b97f4a7c15; 11 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 12 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 13 | return x ^ (x >> 31); 14 | } 15 | 16 | size_t operator()(uint64_t x) const { 17 | static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); 18 | return splitmix64(x + FIXED_RANDOM); 19 | } 20 | }; 21 | 22 | 23 | int main() { 24 | ios::sync_with_stdio(0); 25 | cin.tie(0); 26 | int n, x; 27 | cin >> n >> x; 28 | 29 | vector arr(n); 30 | for (int i = 0; i < n; ++i) { 31 | cin >> arr[i]; 32 | } 33 | 34 | unordered_map prefix_sum_count; 35 | long long current_sum = 0; 36 | long long count = 0; 37 | 38 | // Initialize the map with prefix sum 0 having count 1 (to handle the case when subarray starts from index 0) 39 | prefix_sum_count[0] = 1; 40 | 41 | for (int i = 0; i < n; ++i) { 42 | current_sum += arr[i]; 43 | 44 | // Check if there is a prefix sum such that (current_sum - prefix_sum) == x 45 | if (prefix_sum_count.find(current_sum - x) != prefix_sum_count.end()) { 46 | count += prefix_sum_count[current_sum - x]; 47 | } 48 | 49 | // Update the map with the current prefix sum 50 | prefix_sum_count[current_sum]++; 51 | } 52 | 53 | cout << count << endl; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_1662.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | int n; 7 | 8 | int main() { 9 | 10 | cin >> n; 11 | 12 | vector arr(n); 13 | for (int i = 0; i < n; ++i) { 14 | cin >> arr[i]; 15 | } 16 | 17 | unordered_map remainder_count; 18 | long long prefix_sum = 0; 19 | long long count = 0; 20 | 21 | // Initialize the map with remainder 0 having count 1 (to handle the case when subarray starts from index 0) 22 | remainder_count[0] = 1; 23 | 24 | for (int i = 0; i < n; ++i) { 25 | prefix_sum += arr[i]; 26 | int remainder = ((prefix_sum % n) + n) % n; // Normalize negative remainders 27 | 28 | if (remainder_count.find(remainder) != remainder_count.end()) { 29 | count += remainder_count[remainder]; 30 | } 31 | 32 | remainder_count[remainder]++; 33 | } 34 | 35 | cout << count << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_2162.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | // #include 3 | 4 | // using namespace std; 5 | 6 | // int main() { 7 | // int n; 8 | // cin >> n; 9 | 10 | // vector children(n); 11 | // for (int i = 0; i < n; ++i) { 12 | // children[i] = i + 1; 13 | // } 14 | 15 | // vector removalOrder; 16 | // int current = 0; 17 | // int remaining = n; 18 | 19 | // while (remaining > 0) { 20 | // current = (current + 1) % remaining; // Move to the next child to be removed 21 | // removalOrder.push_back(children[current]); 22 | // children.erase(children.begin() + current); 23 | // --remaining; 24 | // } 25 | 26 | // for (int i = 0; i < n; ++i) { 27 | // cout << removalOrder[i] << " "; 28 | // } 29 | // cout << endl; 30 | 31 | // return 0; 32 | // } 33 | 34 | 35 | #include 36 | #include 37 | 38 | using namespace std; 39 | 40 | int main() { 41 | int n; 42 | cin >> n; 43 | 44 | list children; 45 | for (int i = 1; i <= n; ++i) { 46 | children.push_back(i); 47 | } 48 | 49 | auto it = children.begin(); 50 | while (!children.empty()) { 51 | it = next(it); 52 | if (it == children.end()) { 53 | it = children.begin(); 54 | } 55 | cout << *it << " "; 56 | it = children.erase(it); 57 | if (it == children.end()) { 58 | it = children.begin(); 59 | } 60 | } 61 | 62 | cout << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_2168.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct Range { 8 | int x, y, index; 9 | }; 10 | 11 | bool compareRanges(const Range &a, const Range &b) { 12 | if (a.x != b.x) 13 | return a.x < b.x; 14 | return a.y > b.y; 15 | } 16 | 17 | int main() { 18 | int n; 19 | cin >> n; 20 | 21 | vector ranges(n); 22 | vector contains(n, 0), is_contained(n, 0); 23 | 24 | for (int i = 0; i < n; ++i) { 25 | cin >> ranges[i].x >> ranges[i].y; 26 | ranges[i].index = i; 27 | } 28 | 29 | // Sort ranges by x and by y in descending order for ties 30 | sort(ranges.begin(), ranges.end(), compareRanges); 31 | 32 | // Checking if any range is contained by another 33 | int max_y = -1; 34 | for (int i = 0; i < n; ++i) { 35 | if (ranges[i].y <= max_y) { 36 | is_contained[ranges[i].index] = 1; 37 | } 38 | max_y = max(max_y, ranges[i].y); 39 | } 40 | 41 | // Checking if any range contains another 42 | int min_y = 1e9 + 1; 43 | for (int i = n - 1; i >= 0; --i) { 44 | if (ranges[i].y >= min_y) { 45 | contains[ranges[i].index] = 1; 46 | } 47 | min_y = min(min_y, ranges[i].y); 48 | } 49 | 50 | // Output the results 51 | for (int i = 0; i < n; ++i) { 52 | cout << contains[i] << " "; 53 | } 54 | cout << endl; 55 | for (int i = 0; i < n; ++i) { 56 | cout << is_contained[i] << " "; 57 | } 58 | cout << endl; 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_2183.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | ios::sync_with_stdio(false); 8 | cin.tie(nullptr); 9 | 10 | int n; 11 | cin >> n; 12 | 13 | vector coins(n); 14 | for (int i = 0; i < n; ++i) { 15 | cin >> coins[i]; 16 | } 17 | 18 | sort(coins.begin(), coins.end()); 19 | 20 | long long smallest_unreachable_sum = 1; 21 | for (int i = 0; i < n; ++i) { 22 | if (coins[i] > smallest_unreachable_sum) { 23 | break; 24 | } 25 | smallest_unreachable_sum += coins[i]; 26 | } 27 | 28 | cout << smallest_unreachable_sum << endl; 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_2216.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int n; 6 | int idx[200010]; 7 | 8 | int main() { 9 | cin >> n; 10 | for (int i = 0; i < n; ++i) { 11 | int x; 12 | cin >> x; 13 | idx[x] = i + 1; 14 | } 15 | int ans = 1, pos = 1; 16 | for (int i = 1; i <= n; ++i) { 17 | if (pos > idx[i]) { 18 | ++ans; 19 | } 20 | pos = idx[i]; 21 | } 22 | cout << ans << endl; 23 | return 0; 24 | } 25 | 26 | // g++ -std=c++14 -O2 -Wall cses_2216.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /training-topic/sorting-and-searching/cses_2428.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | int n, k; 7 | 8 | long long countSubarraysWithAtMostKDistinct(const vector& arr, int k) { 9 | int n = arr.size(); 10 | unordered_map freq; 11 | int left = 0, right = 0; 12 | long long count = 0; 13 | int distinct = 0; 14 | 15 | while (right < n) { 16 | // Expand the window by adding arr[right] 17 | if (freq[arr[right]] == 0) { 18 | distinct++; 19 | } 20 | freq[arr[right]]++; 21 | right++; 22 | 23 | // Shrink the window from the left if it has more than k distinct elements 24 | while (distinct > k) { 25 | if (--freq[arr[left]] == 0) { 26 | distinct--; 27 | } 28 | left++; 29 | } 30 | 31 | // Add the number of valid subarrays ending at 'right - 1' 32 | // cout << left << " " << right << endl; 33 | count += (right - left); 34 | } 35 | 36 | return count; 37 | } 38 | 39 | int main() { 40 | 41 | cin >> n >> k; 42 | 43 | vector arr(n); 44 | for (int i = 0; i < n; ++i) { 45 | cin >> arr[i]; 46 | } 47 | 48 | long long result = countSubarraysWithAtMostKDistinct(arr, k); 49 | cout << result << endl; 50 | 51 | return 0; 52 | } 53 | 54 | // g++ cses_2428.cpp -o a && ./a < a.in -------------------------------------------------------------------------------- /training-topic/stdc++.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include // for std::pair 7 | #include // for std::iota 8 | #include // for std::sqrt, std::pow, etc. 9 | 10 | // Add other headers as needed 11 | 12 | int main() { 13 | // Your code here 14 | return 0; 15 | } 16 | 17 | 18 | // bits/stdc++.h - custom version 19 | // This header file includes most of the standard C++ headers 20 | 21 | // C++ Standard Library headers 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | // C Standard Library headers 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | // Add other headers as needed 58 | 59 | // Note: This is not a comprehensive list and may need to be modified 60 | // based on the requirements of your program. 61 | 62 | #include "bits/stdc++.h" 63 | 64 | int main() { 65 | // Your code here 66 | return 0; 67 | } 68 | 69 | // clang++ -std=c++17 -o dsu dsu.cpp 70 | --------------------------------------------------------------------------------