#include <iostream>
#include <list>
#include <utility>

using namespace std;
using namespace rel_ops;

class Monom {
  public:
    int pot;
    double v;

    Monom(double v_ = 0, int pot_=1): pot(pot_), v(v_) {}

    int grad() const { if (v != 0) return pot; else return -1; }

    friend bool operator<(const Monom& m1, const Monom& m2) {
      return m1.grad() > m2.grad();
    }
    friend bool operator==(const Monom& m1, const Monom& m2) {
      return m1.grad() == m2.grad();
    }

    friend ostream& operator<<(ostream& stream, const Monom& m) {
      return stream << showpos << m.v << "x^"
                    << noshowpos << m.pot;
    }
};

class Polynom {
  private:
    list<Monom> ml;

  public:
    Polynom() {}
    Polynom(double v_, int pot_=1): ml({Monom{v_, pot_}}) {}

    Polynom& operator+=(Polynom q) {
      ml.merge(q.ml);
      if (ml.empty()) return *this;
      list<Monom>::iterator curr = ml.begin(),
        next = ++(ml.begin());
      for (; next != ml.end(); ++curr, ++next) {
        if (curr->pot == next->pot) {
          curr->v += next->v;
          *next = Monom{};
        }
      }
      ml.remove(Monom{});
      return *this;
    }

    friend ostream& operator<<(ostream& stream, const Polynom& p) {
      if (p.ml.empty()) return stream << "0";
      for (const auto& monom: p.ml)
        stream << monom;
      return stream;
    }
};

int main() {
  Polynom p, q;
  p += Polynom{4, 3}; p += Polynom{2, 2}; p += Polynom{1, 1};
  q += Polynom{1, 3}; q += Polynom{-2, 2}; q += Polynom{1, 0};

  cout << "p+q: " << (p+=q) << endl;

  return 0;
}
