proconlib

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub anqooqie/proconlib

:heavy_check_mark: Triangular array (tools/triangular_array.hpp)

It is a memory-efficient doubly indexed sequence $a_{i, j}$ such that one of the following conditions holds.

License

Author

Constructor

triangular_array<T, Compare> a(int n);

It is a memory-efficient doubly indexed sequence $a_{i, j}$ such that $0 \leq i < n$, $0 \leq j < n$ and Compare()(i, j).

Constraints

Time Complexity

size

int a.size();

It returns $n$.

Constraints

Time Complexity

operator[]

T& a[i][j];

It is a reference to $a_{i, j}$.

Constraints

Time Complexity

operator>>

std::istream& operator>>(std::istream& is, triangular_array<T, Compare>& a);

It reads $a_{i, j}$ from is in the lexicographic order of $(i, j)$.

Constraints

Time Complexity

Depends on

Verified with

Code

#ifndef TOOLS_TRIANGULAR_ARRAY_HPP
#define TOOLS_TRIANGULAR_ARRAY_HPP

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include "tools/triangular_array_compressor.hpp"

namespace tools {
  template <typename T, typename Compare>
  class triangular_array;

  template <typename T>
  class triangular_array<T, ::std::less<int>> {
    ::tools::triangular_array_compressor<::std::less<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n - 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n - 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i + 1 < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i + 1) - (i + 1));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i + 1 < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i + 1) - (i + 1));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::less<int>>& self) {
      for (int i = 0; i + 1 < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), self.size() - 1 - i, ::std::next(self.m_data.begin(), self.m_comp.compress(i, i + 1)));
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::less_equal<int>> {
    ::tools::triangular_array_compressor<::std::less_equal<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n + 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n + 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i) - i);
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i) - i);
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::less_equal<int>>& self) {
      for (int i = 0; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), self.size() - i, ::std::next(self.m_data.begin(), self.m_comp.compress(i, i)));
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::greater<int>> {
    ::tools::triangular_array_compressor<::std::greater<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n - 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n - 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(1 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(1 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::greater<int>>& self) {
      for (int i = 1; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), i, self[i]);
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::greater_equal<int>> {
    ::tools::triangular_array_compressor<::std::greater_equal<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n + 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n + 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::greater_equal<int>>& self) {
      for (int i = 0; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), i + 1, self[i]);
      }
      return is;
    }
  };
}

#endif
#line 1 "tools/triangular_array.hpp"



#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#line 1 "tools/triangular_array_compressor.hpp"



#line 6 "tools/triangular_array_compressor.hpp"
#include <utility>

namespace tools {
  template <typename Compare>
  class triangular_array_compressor;

  template <>
  class triangular_array_compressor<::std::less<int>> {
    int m_size;

  public:
    triangular_array_compressor() = default;
    triangular_array_compressor(const int n) : m_size(n) {
      assert(n >= 0);
    }

    int size() const {
      return m_size;
    }

    int compress(const int i, const int j) const {
      const auto& n = this->m_size;
      assert(0 <= i && i < j && j < n);
      return (i >= (n + 1) / 2 ? (n - 1 - i) * (n - 1) - 1 : i * (n - 2) - 1) + j;
    }

    ::std::pair<int, int> decompress(const int k) const {
      const auto& n = this->m_size;
      assert(0 <= k && k < n * (n - 1) / 2);
      auto i = k / (n - 1);
      auto j = k % (n - 1);
      if (j < n - 1 - i) {
        j += i + 1;
      } else {
        i = n - 1 - i;
        ++j;
      }
      return {i, j};
    }
  };

  template <>
  class triangular_array_compressor<::std::less_equal<int>> {
    int m_size;

  public:
    triangular_array_compressor() = default;
    triangular_array_compressor(const int n) : m_size(n) {
      assert(n >= 0);
    }

    int size() const {
      return m_size;
    }

    int compress(const int i, const int j) const {
      const auto& n = this->m_size;
      assert(0 <= i && i <= j && j < n);
      return (i >= (n + 1) / 2 ? (n - 1 - i) * (n + 1) + 1 : i * n) + j;
    }

    ::std::pair<int, int> decompress(const int k) const {
      const auto& n = this->m_size;
      assert(0 <= k && k < n * (n + 1) / 2);
      auto i = k / (n + 1);
      auto j = k % (n + 1);
      if (j < n - i) {
        j += i;
      } else {
        i = n - 1 - i;
        --j;
      }
      return {i, j};
    }
  };

  template <>
  class triangular_array_compressor<::std::greater<int>> {
    int m_size;

  public:
    triangular_array_compressor() = default;
    triangular_array_compressor(const int n) : m_size(n) {
      assert(n >= 0);
    }

    int size() const {
      return m_size;
    }

    int compress(const int i, const int j) const {
      const auto& n = this->m_size;
      assert(0 <= j && j < i && i < n);
      return (i >= (n + 1) / 2 ? (n - 1 - i) * n : i * (n - 1)) + j;
    }

    ::std::pair<int, int> decompress(const int k) const {
      const auto& n = this->m_size;
      assert(0 <= k && k < n * (n - 1) / 2);
      auto i = k / (n - 1);
      auto j = k % (n - 1);
      if (i <= j) {
        j -= i;
        i = n - 1 - i;
      }
      return {i, j};
    }
  };

  template <>
  class triangular_array_compressor<::std::greater_equal<int>> {
    int m_size;

  public:
    triangular_array_compressor() = default;
    triangular_array_compressor(const int n) : m_size(n) {
      assert(n >= 0);
    }

    int size() const {
      return m_size;
    }

    int compress(const int i, const int j) const {
      const auto& n = this->m_size;
      assert(0 <= j && j <= i && i < n);
      return (i >= (n + 1) / 2 ? (n - 1 - i) * (n + 1) + n - i : i * (n + 1)) + j;
    }

    ::std::pair<int, int> decompress(const int k) const {
      const auto& n = this->m_size;
      assert(0 <= k && k < n * (n + 1) / 2);
      auto i = k / (n + 1);
      auto j = k % (n + 1);
      if (i + 1 <= j) {
        j -= i + 1;
        i = n - 1 - i;
      }
      return {i, j};
    }
  };
}


#line 11 "tools/triangular_array.hpp"

namespace tools {
  template <typename T, typename Compare>
  class triangular_array;

  template <typename T>
  class triangular_array<T, ::std::less<int>> {
    ::tools::triangular_array_compressor<::std::less<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n - 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n - 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i + 1 < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i + 1) - (i + 1));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i + 1 < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i + 1) - (i + 1));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::less<int>>& self) {
      for (int i = 0; i + 1 < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), self.size() - 1 - i, ::std::next(self.m_data.begin(), self.m_comp.compress(i, i + 1)));
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::less_equal<int>> {
    ::tools::triangular_array_compressor<::std::less_equal<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n + 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n + 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i) - i);
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, i) - i);
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::less_equal<int>>& self) {
      for (int i = 0; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), self.size() - i, ::std::next(self.m_data.begin(), self.m_comp.compress(i, i)));
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::greater<int>> {
    ::tools::triangular_array_compressor<::std::greater<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n - 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n - 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(1 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(1 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::greater<int>>& self) {
      for (int i = 1; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), i, self[i]);
      }
      return is;
    }
  };

  template <typename T>
  class triangular_array<T, ::std::greater_equal<int>> {
    ::tools::triangular_array_compressor<::std::greater_equal<int>> m_comp;
    ::std::vector<T> m_data;
  
  public:
    triangular_array() = default;
    triangular_array(const int n) : m_comp(n), m_data(n * (n + 1) / 2) {
      assert(n >= 0);
    }
    triangular_array(const int n, const T& value) : m_comp(n), m_data(n * (n + 1) / 2, value) {
      assert(n >= 0);
    }

    int size() const {
      return this->m_comp.size();
    }

    ::std::vector<T>::iterator operator[](const int i) {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }
    ::std::vector<T>::const_iterator operator[](const int i) const {
      assert(0 <= i && i < this->size());
      return ::std::next(this->m_data.begin(), this->m_comp.compress(i, 0));
    }

    friend ::std::istream& operator>>(::std::istream& is, ::tools::triangular_array<T, ::std::greater_equal<int>>& self) {
      for (int i = 0; i < self.size(); ++i) {
        ::std::copy_n(::std::istream_iterator<T>(is), i + 1, self[i]);
      }
      return is;
    }
  };
}


Back to top page