diff --git a/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp new file mode 100644 index 000000000..56dcca969 --- /dev/null +++ b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp @@ -0,0 +1,46 @@ +//Program to calculate length of longest increasing subsequence in an array +// in O(n log n) +// tested on : https://cses.fi/problemset/task/1145/ + +#include + +using namespace std; +int LIS(int arr[], int n) +{ + set < int > active; // The current built LIS. + active.insert(arr[0]); + // Loop through every element. + for (int i = 1; i < n; ++i) + { + auto get = active.lower_bound(arr[i]); + if (get == active.end()) + { + active.insert(arr[i]); + } // current element is the greatest so LIS increases by 1. + else + { + int val = * get; // we find the position where arr[i] will be in the LIS. If it is in the LIS already we do nothing + if (val > arr[i]) + { + // else we remove the bigger element and add a smaller element (which is arr[i]) and continue; + active.erase(get); + active.insert(arr[i]); + } + } + } + return active.size(); // size of the LIS. +} +int main(int argc, char const * argv[]) +{ + int n; + cout << "Enter size of array: "; + cin >> n; + int a[n]; + cout << "Enter array elements: "; + for (int i = 0; i < n; ++i) + { + cin >> a[i]; + } + cout << LIS(a, n) << endl; + return 0; +} diff --git a/Graph/lca.cpp b/Graph/lca.cpp new file mode 100644 index 000000000..a69a1a5b3 --- /dev/null +++ b/Graph/lca.cpp @@ -0,0 +1,120 @@ +#include + +using namespace std; +// Find the lowest common ancestor using binary lifting in O(nlogn) +// Zero based indexing +// Resource : https://cp-algorithms.com/graph/lca_binary_lifting.html +const int N = 1005; +const int LG = log2(N) + 1; +struct lca +{ + int n; + vector adj[N]; // Graph + int up[LG][N]; // build this table + int level[N]; // get the levels of all of them + + lca(int n_): n(n_) + { + memset(up, -1, sizeof(up)); + memset(level, 0, sizeof(level)); + for (int i = 0; i < n - 1; ++i) + { + int a, b; + cin >> a >> b; + a--; + b--; + adj[a].push_back(b); + adj[b].push_back(a); + } + level[0] = 0; + dfs(0, -1); + build(); + } + void verify() + { + for (int i = 0; i < n; ++i) + { + cout << i << " : level: " << level[i] << endl; + } + cout << endl; + for (int i = 0; i < LG; ++i) + { + cout << "Power:" << i << ": "; + for (int j = 0; j < n; ++j) + { + cout << up[i][j] << " "; + } + cout << endl; + } + } + + void build() + { + for (int i = 1; i < LG; ++i) + { + for (int j = 0; j < n; ++j) + { + if (up[i - 1][j] != -1) + { + up[i][j] = up[i - 1][up[i - 1][j]]; + } + } + } + } + + void dfs(int node, int par) + { + up[0][node] = par; + for (auto i: adj[node]) + { + if (i != par) + { + level[i] = level[node] + 1; + dfs(i, node); + } + } + } + int query(int u, int v) + { + u--; + v--; + if (level[v] > level[u]) + { + swap(u, v); + } + // u is at the bottom. + int dist = level[u] - level[v]; + // Go up this much distance + for (int i = LG - 1; i >= 0; --i) + { + if (dist & (1 << i)) + { + u = up[i][u]; + } + } + if (u == v) + { + return u; + } + assert(level[u] == level[v]); + for (int i = LG - 1; i >= 0; --i) + { + if (up[i][u] != up[i][v]) + { + u = up[i][u]; + v = up[i][v]; + } + } + assert(up[0][u] == up[0][v]); + return up[0][u]; + } +}; + +int main() +{ + int n; // number of nodes in the tree. + lca l(n); // will take the input in the format given + // n-1 edges of the form + // a b + // Use verify function to see. +} diff --git a/Range queries/bit.cpp b/Range queries/bit.cpp new file mode 100644 index 000000000..449177a77 --- /dev/null +++ b/Range queries/bit.cpp @@ -0,0 +1,76 @@ +// Binary Indexed Tree. +#include + +using namespace std; + +class Bit +{ + int n; + vector bit; + inline int offset(int x) + { + return (x & (-x)); + } + + public: + + Bit(vector& arr) + { + n = arr.size(); + bit.assign(n + 1, 0); + for (int i = 0; i < n; ++i) + { + update(i, arr[i]); + } + } + Bit(int x) + { + n = x; + bit.assign(n + 1, 0); + } + + void update(int id, int val) + { + // Add val at id + id++; + while (id <= n) + { + bit[id] += val; + id += offset(id); + } + } + + int sum(int id) + { + // Get prefix sum upto id. + id++; + int res = 0; + while (id > 0) + { + res += bit[id]; + id -= offset(id); + } + return res; + } + + int sum_range(int l, int r) + { + return sum(r) - sum(l - 1); + } +}; + +int main() +{ + int n = 5; + vector arr = { 1, 2, 3, 4, 5 }; + Bit x(arr); + + assert(x.sum_range(0, 0) == 1); + assert(x.sum_range(0, 1) == 3); + assert(x.sum_range(0, 2) == 6); + x.update(0, 6); + assert(x.sum_range(0, 0) == 6); + assert(x.sum_range(0, 1) == 8); + assert(x.sum_range(0, 2) == 11); + return 0; +}