City is represented by matrix M x N, where rows are enumerated from 1 to N, and columns are enumerated from 1 to M.
Tramways always go straight along the row. Starting point of tramway is (r, c1) and ending point is (r, c2), where r is the number of row, c1 - starting column and c2 - ending column.
We need to determine the number of cells, not occupied by tramways. Attention: tramways can overlap within one row.
Input format: first line contains 3 integer values: N - number of rows, M -number of columns, K - number of tramways. Each next line i from total K lines contains 3 integer values: r, c1, c2.
Output format: integer value that represents the number of cells, not occupied by tramways.
Limitations:
1 <= N, M <= 10^9
0 <= K <= 1000
1 <= r <= N
1 <= c1, c2 <= M
Language: C or C++
Solution:
#include <fstream> template <class T> struct Node { T value; Node *left; // less Node *right; // more bool flag; Node(T value) : value(value), left(0), right(0), flag(false) { } virtual ~Node() { } }; template <class T> class BST { protected: Node<T> *root; virtual Node<T>* constructHelper(T value) { return new Node<T>(value); } Node<T>* getHelper(Node<T> **p, T value) { Node<T> *node, *root, *arr[3]; root = *p; if (root->value > value) { if (!root->left) { node = root->left = constructHelper(value); if (!root->right) root->flag = true; } else { node = getHelper(&root->left, value); if (root->flag) { if (root->left->left) { arr[2] = root->left->left; root->left->left = 0; arr[1] = root->left; root->left->flag = false; root->left = 0; arr[0] = root; root->flag = false; root = arr[1]; root->left = arr[2]; root->right = arr[0]; *p = root; } else if (root->left->right) { arr[2] = root->left->right; root->left->right = 0; arr[1] = root->left; root->left->flag = false; root->left = 0; arr[0] = root; root->flag = false; root = arr[2]; root->left = arr[1]; root->right = arr[0]; *p = root; } } } } else if (root->value < value) { if (!root->right) { node = root->right = constructHelper(value); if (!root->left) root->flag = true; } else { node = getHelper(&root->right, value); if (root->flag) { if (root->right->right) { arr[2] = root->right->right; root->right->right = 0; arr[1] = root->right; root->right->flag = false; root->right = 0; arr[0] = root; root->flag = false; root = arr[1]; root->left = arr[0]; root->right = arr[2]; *p = root; } else if (root->right->left) { arr[2] = root->right->left; root->right->left = 0; arr[1] = root->right; root->right->flag = false; root->right = 0; arr[0] = root; root->flag = false; root = arr[2]; root->left = arr[0]; root->right = arr[1]; *p = root; } } } } else node = root; return node; } void removeHelper(Node<T> *root) { if (root->left) removeHelper(root->left); if (root->right) removeHelper(root->right); delete root; } public: Node<T>* getNode(T value) { Node<T> *node; if (!root) { root = constructHelper(value); node = root; } else { node = getHelper(&root, value); } return node; } BST() : root(0) { } ~BST() { if (root) removeHelper(root); } }; //...................................................................................................................... template <class T, unsigned long long columns_width> class ColumnBST; template <class T, unsigned long long raws_width, unsigned long long columns_width> struct RawNode : public Node<T> { ColumnBST<T, columns_width> *raws[raws_width]; RawNode(T value) : Node(value) { for (T i = 0; i < raws_width; ++i) raws[i] = 0; } virtual ~RawNode() { for (T i = 0; i < raws_width; ++i) if (raws[i]) delete raws[i]; } }; template <class T, unsigned long long raws_width, unsigned long long columns_width> class RawBST : public BST<T> { virtual Node<T>* constructHelper(T value) { return new RawNode<T, raws_width, columns_width>(value); } public: ColumnBST<T, columns_width>* getRaw(T r) { T x, y; RawNode<T, raws_width, columns_width> *node; --r; x = r / raws_width; y = r % raws_width; node = (RawNode<T, raws_width, columns_width>*)getNode(x); if (!node->raws[y]) node->raws[y] = new ColumnBST<T, columns_width>(); return node->raws[y]; } }; //...................................................................................................................... template <class T, unsigned long long columns_width> class RailList; template <class T, unsigned long long columns_width> struct ColumnNode : public Node<T> { RailList<T, columns_width> *rails; ColumnNode(T value) : Node(value), rails(0) { } virtual ~ColumnNode() { if (rails) delete rails; } }; template <class T, unsigned long long columns_width> class ColumnBST : public BST<T> { virtual Node<T>* constructHelper(T value) { return new ColumnNode<T, columns_width>(value); } public: T addRail(T c1, T c2) { T a, b, value; ColumnNode<T, columns_width> *node; --c1; --c2; a = c1 / columns_width; b = c2 / columns_width; if (a == b) { node = (ColumnNode<T, columns_width>*)getNode(a); if (!node->rails) node->rails = new RailList<T, columns_width>(); value = node->rails->addRail(c1 % columns_width, c2 % columns_width); } else { node = (ColumnNode<T, columns_width>*)getNode(a); if (!node->rails) node->rails = new RailList<T, columns_width>(); value = node->rails->addRail(c1 % columns_width, columns_width - 1); ++a; while (a < b) { node = (ColumnNode<T, columns_width>*)getNode(a); if (!node->rails) node->rails = new RailList<T, columns_width>(); value += node->rails->addRail(0, columns_width - 1); ++a; } node = (ColumnNode<T, columns_width>*)getNode(a); if (!node->rails) node->rails = new RailList<T, columns_width>(); value += node->rails->addRail(0, c2 % columns_width); } return value; } }; //...................................................................................................................... template <class T> struct RailNode { RailNode *next; T c1, c2; RailNode(T c1, T c2) : next(0), c1(c1), c2(c2) { } }; template <class T, unsigned long long columns_width> class RailList { RailNode<T> *rail; T total, min, max; T addRailHelper2(RailNode<T> *rail, T c1, T c2) { T value; if (!rail->next) { rail->next = new RailNode<T>(c1, c2); value = (c2 - c1) + 1; } else { value = addRailHelper(rail->next, c1, c2); } return value; } T addRailHelper(RailNode<T> *rail, T c1, T c2) { T value; if ((c1 > rail->c2) || (c2 < rail->c1)) { value = addRailHelper2(rail, c1, c2); } else if ((c1 < rail->c1) || (c2 > rail->c2)) { value = 0; if (c1 < rail->c1) { value += addRailHelper2(rail, c1, rail->c1 - 1); } if (c2 > rail->c2) { value += addRailHelper2(rail, rail->c2 + 1, c2); } } else value = 0; return value; } void removeRailHelper(RailNode<T> *rail) { RailNode<T> *node; while (rail) { node = rail->next; delete rail; rail = node; } } public: RailList() : rail(0), total(0), min(0), max(0) { } ~RailList() { if (rail) removeRailHelper(rail); } T addRail(T c1, T c2) { T value; RailNode<T> *next, *node; if (!rail) { rail = new RailNode<T>(c1, c2); value = (c2 - c1) + 1; min = c1; max = c2; total = value; } else { if (total != columns_width) { if ((c1 > max) || (c2 < min)) { node = new RailNode<T>(c1, c2); next = rail->next; rail->next = node; node->next = next; value = (c2 - c1) + 1; } else { value = addRailHelper(rail, c1, c2); } if (c1 < min) min = c1; if (c2 > max) max = c2; total += value; } else value = 0; } return value; } }; //...................................................................................................................... template <class T, unsigned long long raws_width, unsigned long long columns_width> class City { T n, m, k, i, count; RawBST<T, raws_width, columns_width> *raws; public: City(T n, T m, T k) : i(0), count(0), raws(0) { if (((n >= 1) && (n <= 1000000000)) && ((m >= 1) && (m <= 1000000000)) && (k <= 1000)) { this->n = n; this->m = m; this->k = k; } else throw std::out_of_range(""); } ~City() { if (raws) delete raws; } T getResult() { return ((n * m) - count); } void addRail(T r, T c1, T c2) { ColumnBST<T, columns_width> *raw; if (((i < k) && (r >= 1) && (r <= n)) && ((c1 >= 1) && (c1 <= m)) && ((c2 >= 1) && (c2 <= m) && (c2 >= c1))) { if (!raws) raws = new RawBST<T, raws_width, columns_width>(); raw = raws->getRaw(r); count += raw->addRail(c1, c2); ++i; } else throw std::out_of_range(""); } }; //...................................................................................................................... int main(int argc, char* argv[]) { std::fstream input_file("input.txt", std::ios_base::in); unsigned long long n, m, k; input_file >> n; input_file >> m; input_file >> k; City<unsigned long long, 32, 10000000> *city = new City<unsigned long long, 32, 10000000>(n, m, k); unsigned long long r, c1, c2; for (unsigned long long i = 0; i < k; ++i) { input_file >> r; input_file >> c1; input_file >> c2; city->addRail(r, c1, c2); } unsigned long long result = city->getResult(); delete city; std::fstream output_file("output.txt", std::ios_base::out); output_file << result; return 0; } And it was rejected by employer (Intern C++ developer position). Can you help to figure out whether it is terrible or not? I was never interested in algorithms and I fell like I am C coder that throws all abstractions away. Thank you.
i = 0; i < k; ++i){ input_file >> r; input_file >> c1; input_file >> c2; city->addRail(r, c1, c2);is not meaningful. It's jibberish for someone else who has to work on it. YANA, you are not alone. Posted as a comment because I think code review could do it's work better if the code was more readable. \$\endgroup\$new. \$\endgroup\$