From bae9ae76786cd922ac6d400c19c6fddf152143c8 Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 4 Oct 2019 18:43:42 +0530 Subject: [PATCH 1/8] Added LIS O(nlogn) --- ...Longest Increasing Subsequence (nlogn).cpp | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp diff --git a/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp new file mode 100644 index 000000000..eaf28ff8c --- /dev/null +++ b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp @@ -0,0 +1,39 @@ +//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 active; // The current built LIS. + active.insert(arr[0]); + // Loop through every element. + for(int i=1; i 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; +} From 4961000113393a4bca1294212d31887c2c7862b5 Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 4 Oct 2019 18:55:54 +0530 Subject: [PATCH 2/8] Added BIT --- Range queries/bit.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Range queries/bit.cpp diff --git a/Range queries/bit.cpp b/Range queries/bit.cpp new file mode 100644 index 000000000..1a1d60e36 --- /dev/null +++ b/Range queries/bit.cpp @@ -0,0 +1,66 @@ +// 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 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); + + +} From c45683bb8cb4d4df1d4ddcd19c487cd63c1a6411 Mon Sep 17 00:00:00 2001 From: rohan Date: Fri, 4 Oct 2019 19:05:23 +0530 Subject: [PATCH 3/8] Added LCA binary Lifting O(nlogn) --- Graph/lca.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Graph/lca.cpp diff --git a/Graph/lca.cpp b/Graph/lca.cpp new file mode 100644 index 000000000..b0ff12750 --- /dev/null +++ b/Graph/lca.cpp @@ -0,0 +1,90 @@ +#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>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 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. +} From eb6db42fac506c1a7597e5256c43301ebb55a8ab Mon Sep 17 00:00:00 2001 From: John Law Date: Tue, 8 Oct 2019 23:58:49 +0800 Subject: [PATCH 4/8] Update Longest Increasing Subsequence (nlogn).cpp --- ...Longest Increasing Subsequence (nlogn).cpp | 65 ++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp index eaf28ff8c..56dcca969 100644 --- a/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp +++ b/Dynamic Programming/Longest Increasing Subsequence (nlogn).cpp @@ -3,37 +3,44 @@ // tested on : https://cses.fi/problemset/task/1145/ #include + using namespace std; int LIS(int arr[], int n) { - set active; // The current built LIS. - active.insert(arr[0]); - // Loop through every element. - for(int i=1; i 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) + 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()) { - cin >> a[i]; - } - cout << LIS(a, n) << endl; - return 0; + 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; } From 1b3521d86115bd64fd411311c695dea13ae5c75a Mon Sep 17 00:00:00 2001 From: John Law Date: Wed, 9 Oct 2019 00:00:02 +0800 Subject: [PATCH 5/8] Update lca.cpp --- Graph/lca.cpp | 186 +++++++++++++++++++++++++++++--------------------- 1 file changed, 108 insertions(+), 78 deletions(-) diff --git a/Graph/lca.cpp b/Graph/lca.cpp index b0ff12750..70a9e3e42 100644 --- a/Graph/lca.cpp +++ b/Graph/lca.cpp @@ -1,90 +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 +const int LG = log2(N) + 1; +struct lca +{ + int n; + vector < int > 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>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> 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 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]; - } + 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. +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. } From 883d9dc3a42b565580f130e2f4ff427f9fe64be5 Mon Sep 17 00:00:00 2001 From: John Law Date: Wed, 9 Oct 2019 00:01:36 +0800 Subject: [PATCH 6/8] Update bit.cpp --- Range queries/bit.cpp | 118 +++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/Range queries/bit.cpp b/Range queries/bit.cpp index 1a1d60e36..0a2ba9720 100644 --- a/Range queries/bit.cpp +++ b/Range queries/bit.cpp @@ -1,66 +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 bit; + inline int offset(int x) + { + return (x & (-x)); } - } - int sum(int id){ - // Get prefix sum upto id. - id++; - int res = 0; - while( id > 0 ){ - res += bit[id]; - id -= offset(id); + public: + + Bit(vector < int > & 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); } - return res; - } - int sum_range(int l, int r){ - return sum(r) - sum(l-1); - } + 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); - -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); - - + 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; } From dba806ca60b06611a164283c9bc44c3f3a1f4a22 Mon Sep 17 00:00:00 2001 From: John Law Date: Wed, 9 Oct 2019 00:02:29 +0800 Subject: [PATCH 7/8] Update bit.cpp --- Range queries/bit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Range queries/bit.cpp b/Range queries/bit.cpp index 0a2ba9720..449177a77 100644 --- a/Range queries/bit.cpp +++ b/Range queries/bit.cpp @@ -6,7 +6,7 @@ using namespace std; class Bit { int n; - vector < int > bit; + vector bit; inline int offset(int x) { return (x & (-x)); @@ -14,7 +14,7 @@ class Bit public: - Bit(vector < int > & arr) + Bit(vector& arr) { n = arr.size(); bit.assign(n + 1, 0); @@ -62,7 +62,7 @@ class Bit int main() { int n = 5; - vector arr = { 1, 2, 3, 4, 5 }; + vector arr = { 1, 2, 3, 4, 5 }; Bit x(arr); assert(x.sum_range(0, 0) == 1); From ae701243c2fa6c94fdeecc6535407c90e15b05de Mon Sep 17 00:00:00 2001 From: John Law Date: Wed, 9 Oct 2019 00:02:49 +0800 Subject: [PATCH 8/8] Update lca.cpp --- Graph/lca.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/lca.cpp b/Graph/lca.cpp index 70a9e3e42..a69a1a5b3 100644 --- a/Graph/lca.cpp +++ b/Graph/lca.cpp @@ -9,7 +9,7 @@ const int LG = log2(N) + 1; struct lca { int n; - vector < int > adj[N]; // Graph + vector adj[N]; // Graph int up[LG][N]; // build this table int level[N]; // get the levels of all of them