#include #if __has_include() #include std::istream &operator>>(std::istream &is, atcoder::modint &v) { long long value; is >> value; v = value; return is; } std::ostream &operator<<(std::ostream &os, const atcoder::modint &v) { os << v.val(); return os; } std::ostream &operator<<(std::ostream &os, const atcoder::modint998244353 &v) { os << v.val(); return os; } std::istream &operator>>(std::istream &is, atcoder::modint998244353 &v) { long long x; is >> x; v = x; return is; } std::ostream &operator<<(std::ostream &os, const atcoder::modint1000000007 &v) { os << v.val(); return os; } std::istream &operator>>(std::istream &is, atcoder::modint1000000007 &v) { long long x; is >> x; v = x; return is; } #endif using namespace std; using ll = long long; using lint = __int128_t; using pll = pair; #define newl '\n'; #define rep(i, s, t) for (ll i = s; i < (ll)(t); i++) #define rrep(i, s, t) for (ll i = (ll)(t) - 1; i >= (ll)(s); i--) #define all(x) begin(x), end(x) #define SZ(x) ll(x.size()) #define eb emplace_back #define pb push_back #define TT template TT using vec = vector; TT using vvec = vec>; TT using vvvec = vec>; TT using minheap = priority_queue, greater>; TT using maxheap = priority_queue; TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; } TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; } TT T smod(T x, T mod) { x %= mod; if (x < 0) x += mod; return x; } TT bool rng(T l, T x, T r) { return l <= x && x < r; } TT T flr(T a, T b) { if (b < 0) a = -a, b = -b; return a >= 0 ? a / b : (a + 1) / b - 1; } TT T cil(T a, T b) { if (b < 0) a = -a, b = -b; return a > 0 ? (a - 1) / b + 1 : a / b; } TT T sqr(T x) { return x * x; } //{0, 1, ... } -> {p[0], p[1], ...} template void rearrange(vector &A, vector const &p) { assert(p.size() == A.size()); vector a = A; for (int i = 0; i < ssize(A); ++i) { a[i] = A[p[i]]; } swap(a, A); } template void rearrange(vector &A, vector p, vector &...rest) { rearrange(A, p); (rearrange(rest, p), ...); } template void rearrange(vector &A, Compare cmp, vector &...rest) { vector p(ssize(A)); iota(p.begin(), p.end(), 0); sort(p.begin(), p.end(), cmp); rearrange(A, p); (rearrange(rest, p), ...); } struct io_setup { io_setup() { ios::sync_with_stdio(false); std::cin.tie(nullptr); cout << fixed << setprecision(15); } } io_setup; template ostream &operator<<(ostream &os, const pair &p) { os << p.first << " " << p.second; return os; } TT ostream &operator<<(ostream &os, const vector &v) { for (size_t i = 0; i < v.size(); i++) { os << v[i] << (i + 1 != v.size() ? " " : ""); } return os; } template ostream &operator<<(ostream &os, const array &v) { for (size_t i = 0; i < n; i++) { os << v[i] << (i + 1 != n ? " " : ""); } return os; } template ostream &operator<<(ostream &os, const vvec &v) { for (size_t i = 0; i < v.size(); i++) { os << v[i] << (i + 1 != v.size() ? "\n" : ""); } return os; } TT istream &operator>>(istream &is, vector &v) { for (size_t i = 0; i < v.size(); i++) { is >> v[i]; } return is; } #if __has_include() #include #else #define dbg(...) true #define DBG(...) true #define OUT(...) true #endif const ll inf = LLONG_MAX / 4; int main() { ll n, q; cin >> n >> q; vector know(n, inf); know[0] = -1; vector qs(n, set()); ll ans = 1; // vから伸びる辺であって、時刻 [t, ) で最初を見る auto dfs = [&](auto f, int v, ll t) -> void { if (know[v] > t) return; auto it = qs[v].lower_bound(pll(t, -1)); while (it != qs[v].end()) { auto [p, tar] = *it; if (know[tar] == inf) ans++; if (chmin(know[tar], p)) { f(f, tar, p + 1); it++; continue; } else { qs[v].erase(it++); } } }; rep(i, 0, q) { ll p, x, y; cin >> p >> x >> y; p--, x--, y--; qs[x].insert(pll(p, y)); qs[y].insert(pll(p, x)); dfs(dfs, x, p); dfs(dfs, y, p); cout << ans << endl; } } /* 同じ議論を繰り返さない do smth instead of nothing and stay organized WRITE STUFF DOWN DON'T GET STUCK ON ONE APPROACH */