#include #define ALL(x) (x).begin(),(x).end() #define LB(v,x) (int)(lower_bound(ALL(v),x)-(v).begin()) #define UQ(v) sort(ALL(v)),(v).erase(unique(ALL(v)),(v).end()) #define IO ios::sync_with_stdio(false),cin.tie(nullptr); #define chmax(a,b)(a)=(a)<(b)?(b):(a) #define chmin(a,b)(a)=(a)<(b)?(a):(b) using namespace std; using ll=long long; const int INF=1e9+10; const ll INFL=4e18; /// @brief 遅延評価セグメント木 /// @tparam Monoid モノイド /// @tparam Operator 作用素 /// @tparam mapping (モノイドの元,作用素の元)→モノイドの元を返す関数 template struct SegTreeLazy{ using MonoidType=typename Monoid::Type; using OperatorType=typename Operator::Type; SegTreeLazy()=default; /// @brief 要素数 n の遅延セグ木を構築する SegTreeLazy(int n){ this->n=n; dat.assign(n<<1,Monoid::id()); lazy.assign(n<<1,Operator::id()); } /// @brief 配列 v から遅延セグ木を構築する SegTreeLazy(const vector&v){ this->n=v.size(); dat.assign(n<<1,Monoid::id()); lazy.assign(n<<1,Operator::id()); for(int i=0;i0;i--)dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]); } /// @brief i 番目の要素を x に更新する void set(int i,MonoidType x){ generate_indices(i,i+1); pushdown(); i+=n; dat[i]=x; while(i>>=1)dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]); } /// @brief 区間 [l, r) に x を作用させる void apply(int l,int r,OperatorType x){ if(l==r)return; generate_indices(l,r); pushdown(); l+=n,r+=n; while(l>=1,r>>=1; } pushup(); } /// @brief 区間 [l, r) のモノイド積を返す MonoidType fold(int l,int r){ if(l==r)return Monoid::id(); generate_indices(l,r); pushdown(); MonoidType retl=Monoid::id(),retr=Monoid::id(); l+=n,r+=n; while(l>=1,r>>=1; } return Monoid::op(retl,retr); } template int find_right(int l,F f){ assert(f(Monoid::id())); if(l==n)return n; generate_indices(l,n); pushdown(); l+=n; int r=n+n; vector cand_l,cand_r; while(l>=1,r>>=1; } vectorcand=cand_l; reverse(cand_r.begin(),cand_r.end()); cand.insert(cand.end(),cand_r.begin(),cand_r.end()); MonoidType val=Monoid::id(); for(int i:cand){ if(f(Monoid::op(val,dat[i]))){ val=Monoid::op(val,dat[i]); }else{ while(i int find_left(int r,F f){ assert(f(Monoid::id())); if(r==0)return 0; generate_indices(0,r); pushdown(); r+=n; int l=n; vector cand_l,cand_r; while(l>=1,r>>=1; } vectorcand=cand_r; reverse(cand_l.begin(),cand_l.end()); cand.insert(cand.end(),cand_l.begin(),cand_l.end()); MonoidType val=Monoid::id(); for(int i:cand){ if(f(Monoid::op(dat[i],val))){ val=Monoid::op(dat[i],val); }else{ while(idat; vectorlazy; vectorindices; void generate_indices(int l,int r){ indices.clear(); l+=n,r+=n; int lm=(l/(l&-l))>>1,rm=(r/(r&-r))>>1; while(l>=1,r>>=1; } while(l){ indices.push_back(l); l>>=1; } } void propagate(int i){ if(i=0;j--){ int i=indices[j]; propagate(i); } } void pushup(){ for(int j=0;j<(int)indices.size();j++){ int i=indices[j]; dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]); } } }; /// @file monoid.hpp /// @brief モノイド namespace Monoid{ /// @brief Min モノイド /// @tparam max_value 単位元 template struct Min{ using Type=T; static Type id(){return max_value;} static Type op(const Type&a,const Type&b){return min(a,b);} }; /// @brief Max モノイド /// @tparam min_value 単位元 template struct Max{ using Type=T; static Type id(){return min_value;} static Type op(const Type&a,const Type&b){return max(a,b);} }; /// @brief 和 template struct Sum{ using Type=T; static Type id(){return 0;} static Type op(const Type&a,const Type&b){return a+b;} }; /// @brief (和,区間の長さ) template struct SumPair{ using Type=pair; static Type id(){return make_pair(T(0),0);} static Type op(const Type&a,const Type&b){return{a.first+b.first,a.second+b.second};} }; } namespace Operator{ template struct Update{ using Type=T; static Type id(){return not_exist;} static Type op(const Type&a,const Type&b){return b==id()?a:b;} }; template struct Add{ using Type=T; static Type id(){return 0;} static Type op(const Type&a,const Type&b){return a+b;} }; template struct UpdateTimeStamp{ using Type=pair; static Type id(){return {0,-1};} static Type op(const Type&a,const Type&b){return b.second>a.second?b:a;} }; } namespace RangeQuery{ template struct Update_GetMin{ static T mapping(const T&a,const T&b){return b==not_exist?a:b;} using Type=struct SegTreeLazy,Operator::Update,mapping>; }; template struct Update_GetMax{ static T mapping(const T&a,const T&b){return b==not_exist?a:b;} using Type=struct SegTreeLazy,Operator::Update,mapping>; }; template struct Update_GetSum{ using S=typename Monoid::SumPair::Type; static S mapping(const S&a,const T&b){return b==not_exist?a:S{b*a.second,a.second};} using Type=struct SegTreeLazy,Operator::Update,mapping>; }; template struct Add_GetMin{ static T mapping(const T&a,const T&b){return a+b;} using Type=struct SegTreeLazy,Operator::Add,mapping>; }; template struct Add_GetMax{ static T mapping(const T&a,const T&b){return a+b;} using Type=struct SegTreeLazy,Operator::Add,mapping>; }; template struct Add_GetSum{ using S=typename Monoid::SumPair::Type; static S mapping(const S&a,const T&b){return{a.first+b*a.second,a.second};} using Type=struct SegTreeLazy,Operator::Add,mapping>; }; } struct Info{ int minval,mincnt; Info(int x=0,int y=1){minval=x,mincnt=y;} }; struct Mono{ using Type=Info; static Type op(Type l,Type r){ if(l.minval==r.minval){ return Info(l.minval,l.mincnt+r.mincnt); }else if(l.minval>N; vectorinit(N,Info()); SegTreeLazyseg(init); int Q;cin>>Q; vector>query(Q); for(int q=0;q>t; if(t==1){ int l,r;cin>>l>>r; l--,r--; query[q]={l,r}; seg.apply(l,r,1); } else if(t==2){ int p;cin>>p,p--; auto[l,r]=query[p]; seg.apply(l,r,-1); } else{ Info res=seg.fold(0,N); int ans=res.mincnt; if(res.minval!=0)ans=0; cout<