#line 1 "freespace/main.cpp" #include #line 1 "library/gandalfr/data_structure/dual_segment_tree.hpp" #line 7 "library/gandalfr/data_structure/dual_segment_tree.hpp" #include /* * verify : https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=7627486#1 */ template class dual_segment_tree{ private: int n, vec_size; const T e; const std::function< T(T, T) > op; std::vector v; public: // 要素の配列 vec で初期化 dual_segment_tree(const std::vector &vec, const std::function< T(T, T) > &f, T _e) : vec_size(vec.size()), op(f), e(_e) { int siz = vec.size(); n = 1; while(n < siz) n *= 2; v.resize(2 * n - 1, e); for(int i = 0; i < siz; i++) v[i + n - 1] = vec[i]; } // 長さ siz の単位元の配列で初期化 dual_segment_tree(int siz, const std::function< T(T, T) > &f, T _e) : vec_size(siz), op(f), e(_e) { n = 1; while(n < siz) n *= 2; v.resize(2 * n - 1, e); } // pos 番目の値を得る T get(int pos){ pos += n - 1; T ret = v[pos]; while(pos > 0){ pos = (pos - 1) / 2; ret = op(ret, v[pos]); } return ret; } // [l, r) に action を作用する void act(int l, int r, T action){ assert(0 <= l && l <= r && r <= vec_size); if(l == r) return; act(l, r, 0, 0, n, action); } void print(){ for(int i = 0; i < vec_size; i++){ std::cout << get(i) << (i == vec_size - 1 ? "" : " "); } std::cout << std::endl; } private: void act(int a, int b, int k, int l, int r, T action){ if(r <= a || b <= l) return; if(a <= l && r <= b){ v[k] = op(v[k], action); return; } act(a, b, 2 * k + 1, l, (l + r) / 2, action); act(a, b, 2 * k + 2, (l + r) / 2, r, action); } }; template struct RAQ_dual_segment_tree : public dual_segment_tree{ RAQ_dual_segment_tree(int size) : RAQ_dual_segment_tree::dual_segment_tree(size, [](T a, T b){ return a + b; }, 0) {}; RAQ_dual_segment_tree(const std::vector &vec) : RAQ_dual_segment_tree::dual_segment_tree(vec, [](T a, T b){ return a + b; }, 0) {}; }; /* * verify : https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=7627473#1 */ template class RUQ_dual_segment_tree{ private: int n, tm = 0, vec_size; std::vector> v; public: // 要素の配列 vec で初期化 RUQ_dual_segment_tree(const std::vector &vec) : vec_size(vec.size()) { int siz = vec.size(); n = 1; while(n < siz) n *= 2; v.resize(2 * n - 1); for(auto &x : v) x.first = -1; for(int i = 0; i < siz; i++) v[i + n - 1].second = vec[i]; } // 長さ siz の単位元の配列で初期化 RUQ_dual_segment_tree(int siz) : vec_size(siz) { n = 1; while(n < siz) n *= 2; v.resize(2 * n - 1); for(auto &x : v) x.first = -1; } // pos 番目の値を得る T get(int pos){ pos += n - 1; std::pair ret = v[pos]; while(pos > 0){ pos = (pos - 1) / 2; ret = std::max(ret, v[pos]); } return ret.second; } // [l, r) に action を作用する void act(int l, int r, T action){ assert(0 <= l && l <= r && r <= vec_size); if(l == r) return; act(l, r, 0, 0, n, {tm, action}); tm++; } void print(){ for(int i = 0; i < vec_size; i++){ std::cout << get(i) << (i == vec_size - 1 ? "" : " "); } std::cout << std::endl; } private: void act(int a, int b, int k, int l, int r, std::pair action){ if(r <= a || b <= l) return; if(a <= l && r <= b){ v[k] = std::max(v[k], action); return; } act(a, b, 2 * k + 1, l, (l + r) / 2, action); act(a, b, 2 * k + 2, (l + r) / 2, r, action); } }; #line 1 "library/gandalfr/other/io_supporter.hpp" #line 7 "library/gandalfr/other/io_supporter.hpp" std::ostream &operator<<(std::ostream &dest, __uint128_t value) { std::ostream::sentry s(dest); if (s) { __uint128_t tmp = value; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } std::ostream &operator<<(std::ostream &dest, __int128_t value) { std::ostream::sentry s(dest); if (s) { __int128_t tmp = value < 0 ? -value : value; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) { --d; *d = '-'; } int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } template std::ostream &operator<<(std::ostream &os, const std::vector &v) { for(int i=0; i<(int)v.size(); i++) os << v[i] << (i+1 != (int)v.size() ? " " : ""); return os; } template std::istream &operator>>(std::istream &is, std::vector &v){ for(T &in : v) is >> in; return is; } template std::ostream &operator<<(std::ostream &os, const std::pair& p) { os << p.first << " " << p.second; return os; } template std::istream &operator>>(std::istream &is, std::pair &p) { is >> p.first >> p.second; return is; } template std::ostream &operator<<(std::ostream &os, std::queue v) { int N = v.size(); for(int i=0; i std::istream &operator>>(std::istream &is, std::queue &v) { for(T &in : is) v.push(is); return is; } template std::ostream &operator<<(std::ostream &os, const std::set &st) { for(const T &x : st){ std::cout << x << " "; } return os; } template std::ostream &operator<<(std::ostream &os, const std::multiset &st) { for(const T &x : st){ std::cout << x << " "; } return os; } #line 4 "freespace/main.cpp" using namespace std; using ll = long long; const int INF = 1001001001; const int MAXINT = std::numeric_limits::max(); const int MININT = std::numeric_limits::min(); const ll INFL = 1001001001001001001; const ll MAXLL = std::numeric_limits::max(); const ll MINLL = std::numeric_limits::min(); const ll MOD = 1000000007; const ll _MOD = 998244353; #define rep(i, j, n) for(ll i = (ll)(j); i < (ll)(n); i++) #define rrep(i, j, n) for(ll i = (ll)(n-1); i >= (ll)(j); i--) #define fore(i,a) for(auto &i : a) #define all(a) (a).begin(),(a).end() #define lr(a, l, r) (a).begin()+(l),(a).begin()+(r) #define LF cout << endl int main(void){ /*ifstream in("input.txt"); cin.rdbuf(in.rdbuf()); ofstream fout("output.txt");*/ //input int N, M; cin >> N >> M; dual_segment_tree> seg(N, [](pair a, pair b){ return max(a, b); }, {MININT, 'S'}); rep(i,0,M){ int l, r; char c; cin >> l >> r >> c; l--; seg.act(l, r, {-i, c}); } //calculate vector cnt(3, 0); rep(i,0,N){ if(seg.get(i).second == 'Y') cnt[0]++; if(seg.get(i).second == 'K') cnt[1]++; if(seg.get(i).second == 'C') cnt[2]++; } cout << cnt << endl; }