#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define INF 100000000 #define INF_INT_MAX 2147483647 #define INF_LL_MAX 9223372036854775807 #define EPS 1e-10 #define Pi acos(-1) #define LL long long #define ULL unsigned long long using namespace std; #define int long long typedef pair II; const int MAX_SEG = 1 << 17; struct Node{ int red, blue; int lazy_red, lazy_blue; bool lazyFlag; //伝播させるかどうか Node(){ red = blue = 0; lazy_red = lazy_blue = 0; lazyFlag = false; } }; Node seg[2*MAX_SEG]; int n; void Init(int _n){ n = 1; while(_n > n) n *= 2; } //遅延評価 inline void lazy_evaluate_node(int k, int a, int b){ if(!seg[k].lazyFlag) return; //現在見ているノードを遅延評価の値で評価する seg[k].red = seg[k].lazy_red*(b-a); seg[k].blue = seg[k].lazy_blue*(b-a); //今見ているノードが末端ノードでないなら //子ノードに遅延を伝播させる if(k < n-1){ seg[2*k+1].lazy_red = seg[k].lazy_red; seg[2*k+1].lazy_blue = seg[k].lazy_blue; seg[2*k+2].lazy_red = seg[k].lazy_red; seg[2*k+2].lazy_blue = seg[k].lazy_blue; seg[2*k+1].lazyFlag = true; seg[2*k+2].lazyFlag = true; } seg[k].lazyFlag = false; } //実際の評価 //kの子が評価されていることが前提 inline void update_node(int k){ seg[k].red = seg[2*k+1].red + seg[2*k+2].red; seg[k].blue = seg[2*k+1].blue + seg[2*k+2].blue; } //[l,r)の区間を指定した色で塗る void update_range(int l, int r, int red_v, int blue_v, int k = 0, int a = 0, int b = n){ //とりあえず伝播 lazy_evaluate_node(k,a,b); //今見ているノード[a,b)が更新したい区間[l,r)と重なっていない時 if(b <= l || r <= a) return; //今見ているノードが更新したい区間に完全に含まれている時 else if(l <= a && b <= r){ seg[k].lazy_red = red_v; seg[k].lazy_blue = blue_v; seg[k].lazyFlag = true; lazy_evaluate_node(k,a,b); return; } //今見ているノードが更新したい区間に微妙に含まれている時 else{ int mid = (a+b)/2; update_range(l,r,red_v,blue_v,2*k+1,a,mid); update_range(l,r,red_v,blue_v,2*k+2,mid,b); update_node(k); } } //[l, r)に関するクエリ first := red second := blue II Query(int l, int r, int k = 0, int a = 0, int b = n){ //とりあえず伝播 lazy_evaluate_node(k,a,b); //交差しない場合 if(b <= l || r <= a) return II(0,0); //完全に含む場合 else if(l <= a && b <= r){ return II(seg[k].red,seg[k].blue); } //交差する場合 else{ int mid = (a+b)/2; II p1 = Query(l,r,2*k+1,a,mid); II p2 = Query(l,r,2*k+2,mid,b); update_node(k); return II(p1.first+p2.first, p1.second+p2.second); } } #define MAX_N 100001 #define MAX_Q 100001 int N, Q; signed main(){ cin >> N; cin >> Q; Init(N); LL RedScore = 0, BlueScore = 0; for(int q = 0; q < Q; q++){ int x,l,r; cin >> x >> l >> r; r++; if(x == 0){ II p = Query(l,r); if(p.first > p.second) RedScore += p.first; else if(p.first < p.second) BlueScore += p.second; } else if(x == 1){ update_range(l,r,1,0); } else if(x == 2){ update_range(l,r,0,1); } } II p = Query(0, N); RedScore += p.first; BlueScore += p.second; cout << RedScore << " " << BlueScore << endl; /* for(int i = 0; i < N+n-1; i++){ fprintf(stderr, "Node:%d red:%d blue:%d\n", i, seg[i].red, seg[i].blue); } */ return 0; }