#include #include #include using namespace std; #define N_MAX (1<<17) class SegTreeLazy{ private: int val[(2*N_MAX)+1]; // その領域の int lazy[(2*N_MAX)+1]; // -1でない時、その領域はすべてlazy[?]で満たされているとする public: SegTreeLazy(){ for( int i = 0 ; i < (2*N_MAX)+1; i++ ){ val[i]=0; lazy[i]=-1; } } inline int evalAll(int v, int l=1, int r=N_MAX+1 ){ //val[k] が示す[l,r)の範囲には各要素の値としてvのみ入っている。 //この場合のval[k]の算出式をここで定義する。 //大体は総和な気がするけれど、最大値や最小値だった時にはここの値を定義し直す必要がある。 return (r-l)*v; } inline int combine( int x, int y ){ // 二つの範囲の代表値x,yを与えられた時に何を返すか // 大体は総和なきがするけど、最大値や最小値だった時には(ry) return x+y; } inline int lazy_eval(int l=1, int r=N_MAX+1, int k=1){ if( lazy[k]!=-1 ){ if( k*2+1 <= 2*(N_MAX)+1 ){ val[k*2]=val[k*2+1]=0; lazy[k*2]=lazy[k*2+1]=lazy[k]; } val[k]=evalAll(lazy[k],l,r); lazy[k]=-1; } return val[k]; } int getVal(int x, int y, int l=1, int r=N_MAX+1,int k=1 ){ //get data in [x,y) //val[k]=data in [l,r) if( l>=r ) return 0; // エラー値なので状況次第で変更する。 if( y<=l || r<=x ) return 0; // 同上 if( x<=l && r<=y ) return lazy_eval(l,r,k); lazy_eval(l,r,k); int m=(l+r)/2; return combine(getVal(x,y,l,m,k*2),getVal(x,y,m,r,k*2+1)); } void fill(int x, int y, int v, int l=1, int r=N_MAX+1,int k=1 ){ //fill data v in [x,y) //val[k]= data in [l,r) lazy_eval(l,r,k); if( l>= r ) return; if( y<=l || r<=x ) return; if( x<=l && r<=y ){ lazy[k]=v; lazy_eval(l,r,k); return; } int m=(l+r)/2; fill(x,y,v,l,m,k*2); fill(x,y,v,m,r,1+k*2); val[k]=combine(val[k*2],val[k*2+1]); } void print(int l=1, int r=N_MAX+1, int k=1){ cout << l << "-"<> N >> Q; long long pointA=0; long long pointB=0; for( int i =0 ; i < Q; i++ ){ int x,l,r; scanf("%d%d%d",&x,&l,&r); if( x!=0 ){ seg[x-1].fill(l+1,r+2,1); seg[2-x].fill(l+1,r+2,0); //seg[0].print(); } else{ int numA= seg[0].getVal(l+1,r+2); int numB= seg[1].getVal(l+1,r+2); if( numA > numB) pointA+=numA; if( numB > numA) pointB+=numB; } } pointA += seg[0].getVal(1,N+1); pointB += seg[1].getVal(1,N+1); cout << pointA << " " << pointB<