Problem: Pavel is going to make a game of his dream. However, he knows that he can't make it on his own so he founded a development company and hired n workers of staff. Now he wants to pick n workers from the staff who will be directly responsible for developing a game.

Each worker has a certain skill level vi. Besides, each worker doesn't want to work with the one whose skill is very different. In other words, the i-th worker won't work with those whose skill is less than li, and with those whose skill is more than ri.

Pavel understands that the game of his dream isn't too hard to develop, so the worker with any skill will be equally useful. That's why he wants to pick a team of the maximum possible size. Help him pick such team.

Input

The first line contains a single integer n (1 ≤ n ≤ 105) — the number of workers Pavel hired.

Each of the following n lines contains three space-separated integers li, vi, ri (1 ≤ li ≤ vi ≤ ri ≤ 3·105) — the minimum skill value of the workers that the i-th worker can work with, the i-th worker's skill and the maximum skill value of the workers that the i-th worker can work with.

Output

In the first line print a single integer m — the number of workers Pavel must pick for developing the game.

In the next line print m space-separated integers — the numbers of the workers in any order.

If there are multiple optimal solutions, print any of them.

Examples

Input

4
2 8 9
1 4 7
3 6 8
5 8 10


Output

3
1 3 4


Input

6
3 5 16
1 6 11
4 8 12
7 9 16
2 10 14
8 13 15


Output

4
1 2 3 5

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
bool __hack = std::ios::sync_with_stdio(false);
auto __hack1 = cin.tie(nullptr);
template <class T>
inline T mn(T arg) {
  return arg;
}
template <class T, class... Args>
inline bool rmn(T& to, Args... args) {
  auto v = mn(args...);
  if (to > v) {
    to = v;
    return true;
  }
  return false;
}
namespace template_util {
constexpr int bytecount(uint64_t x) { return x ? 1 + bytecount(x >> 8) : 0; }
template <int N>
struct bytetype {};
template <>
struct bytetype<4> {};
template <>
struct bytetype<3> {};
template <>
struct bytetype<2> {};
template <>
struct bytetype<1> {};
template <>
struct bytetype<0> {};
template <uint64_t N>
struct minimal_uint : bytetype<bytecount(N)> {};
}  // namespace template_util
template <class T>
T next(istream& in) {
  T ret;
  in >> ret;
  return ret;
}
namespace option_detail {
struct NoneHelper {};
}  // namespace option_detail
template <class Value>
class Option {
 public:
  static_assert(!std::is_reference<Value>::value,
                "Option may not be used with reference types");
  static_assert(!std::is_abstract<Value>::value,
                "Option may not be used with abstract types");
  Value* get_pointer() && = delete;

 private:
  struct StorageTriviallyDestructible {
    bool hasValue;
  };
  struct StorageNonTriviallyDestructible {
    union {
      Value value;
    };
    bool hasValue;
    ~StorageNonTriviallyDestructible() { clear(); }
    void clear() {
      if (hasValue) {
        hasValue = false;
        value.~Value();
      }
    }
  };
  using Storage =
      typename std::conditional<std::is_trivially_destructible<Value>::value,
                                StorageTriviallyDestructible,
                                StorageNonTriviallyDestructible>::type;
  Storage storage_;
};
template <class V>
bool operator<(const Option<V>&, const V& other) = delete;
template <class V>
bool operator<=(const Option<V>&, const V& other) = delete;
template <class V>
bool operator>=(const Option<V>&, const V& other) = delete;
template <class V>
bool operator>(const Option<V>&, const V& other) = delete;
template <class V>
bool operator<(const V& other, const Option<V>&) = delete;
template <class V>
bool operator<=(const V& other, const Option<V>&) = delete;
template <class V>
bool operator>=(const V& other, const Option<V>&) = delete;
template <class V>
bool operator>(const V& other, const Option<V>&) = delete;
namespace index_iterator_impl {
template <class T>
struct member_dispatch_helper {
 private:
  T value;
};
template <class C, bool reverse = false>
struct index_iterator {
  typedef decltype(((C*)nullptr)->operator[](size_t(0))) reference;
  typedef conditional<
      is_reference<reference>::value,
      typename add_pointer<typename remove_reference<reference>::type>::type,
      member_dispatch_helper<typename remove_reference<reference>::type>>
      pointer;
  static const ptrdiff_t dir = reverse ? -1 : 1;
  index_iterator() = default;
  inline bool operator!=(const index_iterator<C, reverse>& o) {
    return index != o.index;
  }
  inline bool operator<(const index_iterator<C, reverse>& o) {
    return reverse ? index > o.index : index < o.index;
  }
  inline bool operator>(const index_iterator<C, reverse>& o) {
    return reverse ? index < o.index : index > o.index;
  }
  inline bool operator<=(const index_iterator<C, reverse>& o) {
    return reverse ? index >= o.index : index <= o.index;
  }
  inline bool operator>=(const index_iterator<C, reverse>& o) {
    return reverse ? index <= o.index : index >= o.index;
  }
  inline reference operator*() { return (*container)[index]; }
  inline const reference operator*() const { return (*container)[index]; }
  inline pointer operator->() { return pointer((*container)[index]); }
  inline index_iterator<C, reverse>& operator++() {
    index += dir;
    return *this;
  }
  inline index_iterator<C, reverse> operator++(int) {
    auto copy = *this;
    index += dir;
    return copy;
  }
  inline index_iterator<C, reverse>& operator--() {
    index -= dir;
    return *this;
  }
  inline index_iterator<C, reverse> operator--(int) {
    auto copy = *this;
    index -= dir;
    return copy;
  }
  inline index_iterator<C, reverse>& operator+=(ptrdiff_t n) {
    index += dir * n;
    return *this;
  };
  inline index_iterator<C, reverse>& operator-=(ptrdiff_t n) {
    index -= dir * n;
    return *this;
  };
  inline friend index_iterator<C, reverse> operator-(
      index_iterator<C, reverse> a, ptrdiff_t n) {
    return a -= n;
  };
  inline friend index_iterator<C, reverse> operator+(
      ptrdiff_t n, index_iterator<C, reverse> a) {
    return a += n;
  };
  inline friend index_iterator<C, reverse> operator+(
      index_iterator<C, reverse> a, ptrdiff_t n) {
    return a += n;
  };
  inline friend ptrdiff_t operator-(const index_iterator<C, reverse>& a,
                                    const index_iterator<C, reverse>& b) {
    return dir * (a.index - b.index);
  };
  inline reference operator[](ptrdiff_t n) {
    return (*container)[index + dir * n];
  };
  inline const reference operator[](ptrdiff_t n) const {
    return (*container)[index + dir * n];
  };

 private:
  C* container;
  ptrdiff_t index;
};
}  // namespace index_iterator_impl
namespace multivec_impl {
template <template <class, size_t> class Base, class T, size_t NDIMS>
struct vec_mixin : public Base<T, NDIMS> {
  using Base<T, NDIMS>::Base;
};
}  // namespace multivec_impl
namespace segment_tree_impl {
size_t calc_size(size_t n) {
  size_t ret = 1;
  while (ret < n) {
    ret *= 2;
  }
  return ret;
}
}  // namespace segment_tree_impl
namespace segment_tree {
template <class T>
struct val_traits {};
template <class T, class U>
struct update_traits {};
struct dummy_update {};
template <class T>
struct range_min {
  T val_;
  range_min() : val_(numeric_limits<T>::min()){};
  range_min(T val) : val_(val){};
};
template <class T>
struct val_traits<range_min<T>> {
  static inline range_min<T> zero() { return {}; };
  static inline void compose(range_min<T>& a, range_min<T> b) {
    rmn(a.val_, b.val_);
  }
};
template <class T, class U = dummy_update>
struct stree {
  using VT = val_traits<T>;
  using UT = update_traits<T, U>;
  template <class F>
  stree(size_t n, F f)
      : n_(n),
        size(segment_tree_impl::calc_size(n)),
        ar(size - 1 + n),
        ur(size - 1 + n, UT::one()) {
    for (int i = 0; i < n; ++i) {
      ar[size - 1 + i] = f(i);
    }
    for (int i = size - 2; i >= 0; --i) {
      ar[i] = 2 * i + 1 < ar.size() ? ar[2 * i + 1] : VT::zero();
      if (2 * i + 2 < ar.size()) {
        VT::compose(ar[i], ar[2 * i + 2]);
      }
    }
  }
  T sumRange(size_t l, size_t r) {
    assert(l < r && r <= n_);
    return sumRange(0, 0, size, l, r);
  }
  T updateRange(size_t l, size_t r, U u) {
    assert(l < r && r <= n_);
    return updateRange(0, 0, size, l, r, u);
  }

 private:
  T sumRange(size_t n, size_t nl, size_t nr, size_t l, size_t r) {
    assert(l < nr && nl < r);
    if (l <= nl && nr <= r) {
      return ar[n];
    }
    size_t mid = (nl + nr) / 2;
    T ret;
    if (r <= mid) {
      ret = sumRange(2 * n + 1, nl, mid, l, r);
    } else if (mid <= l) {
      ret = sumRange(2 * n + 2, mid, nr, l, r);
    } else {
      ret = sumRange(2 * n + 1, nl, mid, l, r);
      VT::compose(ret, sumRange(2 * n + 2, mid, nr, l, r));
    }
    UT::apply(ret, ur[n], max(l, nl), min(r, nr));
    return ret;
  }
  inline void propagate_down(size_t n, size_t nl, size_t mid, size_t nr) {
    UT::apply(ar[2 * n + 1], ur[n], nl, mid);
    UT::compose(ur[2 * n + 1], ur[n]);
    if (2 * n + 2 < ar.size()) {
      UT::apply(ar[2 * n + 2], ur[n], mid, nr);
      UT::compose(ur[2 * n + 2], ur[n]);
    }
    ur[n] = UT::one();
  }
  T updateRange(size_t n, size_t nl, size_t nr, size_t l, size_t r, U u) {
    assert(l < nr && nl < r);
    if (l <= nl && nr <= r) {
      UT::apply(ar[n], u, nl, nr);
      UT::compose(ur[n], u);
      return ar[n];
    }
    size_t mid = (nl + nr) / 2;
    propagate_down(n, nl, mid, nr);
    ar[n] = mid <= l ? ar[2 * n + 1] : updateRange(2 * n + 1, nl, mid, l, r, u);
    VT::compose(ar[n], r <= mid ? ar[2 * n + 2]
                                : updateRange(2 * n + 2, mid, nr, l, r, u));
    return ar[n];
  }
  const size_t n_, size;
  vector<T> ar;
  vector<U> ur;
};
}  // namespace segment_tree
using namespace segment_tree;
struct Event {
  int x, from, to;
  bool enter;
  Event(int x, int from, int to, bool enter)
      : x(x), from(from), to(to), enter(enter) {}
  bool operator<(const Event& e) const {
    if (x != e.x) {
      return x < e.x;
    }
    if (enter != e.enter) {
      return !enter;
    }
    return make_pair(from, to) < make_pair(e.from, e.to);
  }
};
using Val = range_min<pair<int, int>>;
namespace segment_tree {
template <>
struct update_traits<Val, int> {
  static inline int one() { return 0; }
  static inline void compose(int& a, const int b) { a += b; }
  static inline void apply(Val& a, const int b, size_t, size_t) {
    a.val_.first += b;
  }
};
}  // namespace segment_tree
void solve(istream& in, ostream& out) {
  int n = next<int>(in);
  vector<int> left(n), right(n), v(n);
  for (int i = 0; i < (n); ++i) {
    left[i] = next<int>(in);
    v[i] = next<int>(in);
    right[i] = next<int>(in);
  }
  vector<Event> events;
  events.reserve(2 * n);
  for (int i = 0; i < (n); ++i) {
    events.emplace_back(Event(v[i], left[i], v[i], true));
    events.emplace_back(Event(right[i] + 1, left[i], v[i], false));
  }
  sort(events.begin(), events.end());
  stree<Val, int> tree(1 << 19,
                       [&](size_t i1) { return make_pair(0, (int)i1); });
  int best_x = -1, best_y = -1, best = 0;
  for (const Event& e : events) {
    int value = e.enter ? -1 : 1;
    tree.updateRange(e.from, e.to + 1, value);
    Val p = tree.sumRange(e.from, e.to + 1);
    if (-p.val_.first > best) {
      best = -p.val_.first;
      best_x = e.x;
      best_y = p.val_.second;
    }
  }
  out << best << endl;
  for (int i = 0; i < (n); ++i) {
    if (left[i] <= best_y && v[i] >= best_y && right[i] >= best_x &&
        v[i] <= best_x) {
      out << i + 1 << ' ';
    }
  }
  out << endl;
}
int main() {
  solve(cin, cout);
  return 0;
}