結果
| 問題 |
No.3094 Stapler
|
| コンテスト | |
| ユーザー |
Today03
|
| 提出日時 | 2025-04-07 02:32:00 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 92 ms / 2,000 ms |
| コード長 | 8,467 bytes |
| コンパイル時間 | 3,068 ms |
| コンパイル使用メモリ | 285,388 KB |
| 実行使用メモリ | 35,364 KB |
| 最終ジャッジ日時 | 2025-10-23 22:26:36 |
| 合計ジャッジ時間 | 9,725 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 72 |
ソースコード
#include<bits/stdc++.h>
#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<typename Monoid,typename Operator,auto mapping>
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<MonoidType>&v){
this->n=v.size();
dat.assign(n<<1,Monoid::id());
lazy.assign(n<<1,Operator::id());
for(int i=0;i<n;i++)dat[i+n]=v[i];
for(int i=n-1;i>0;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<r){
if(l&1){
lazy[l]=Operator::op(lazy[l],x);
dat[l]=mapping(dat[l],x);
l++;
}
if(r&1){
r--;
lazy[r]=Operator::op(lazy[r],x);
dat[r]=mapping(dat[r],x);
}
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<r){
if(l&1)retl=Monoid::op(retl,dat[l++]);
if(r&1)retr=Monoid::op(dat[--r],retr);
l>>=1,r>>=1;
}
return Monoid::op(retl,retr);
}
template<typename F>
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<int> cand_l,cand_r;
while(l<r){
if(l&1)cand_l.push_back(l++);
if(r&1)cand_r.push_back(--r);
l>>=1,r>>=1;
}
vector<int>cand=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<n){
propagate(i);
i<<=1;
if(f(Monoid::op(val,dat[i]))){
val=Monoid::op(val,dat[i]);
i|=1;
}
}
return i-n;
}
}
return n;
}
template<typename F>
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<int> cand_l,cand_r;
while(l<r){
if(l&1)cand_l.push_back(l++);
if(r&1)cand_r.push_back(--r);
l>>=1,r>>=1;
}
vector<int>cand=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(i<n){
propagate(i);
i=(i<<1)|1;
if(f(Monoid::op(dat[i],val))){
val=Monoid::op(dat[i],val);
i^=1;
}
}
return i-n+1;
}
}
return 0;
}
int size(){return n;}
MonoidType operator[](int i){return fold(i,i+1);}
private:
int n;
vector<MonoidType>dat;
vector<OperatorType>lazy;
vector<int>indices;
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<r){
if(l<=lm)indices.push_back(l);
if(r<=rm)indices.push_back(r);
l>>=1,r>>=1;
}
while(l){
indices.push_back(l);
l>>=1;
}
}
void propagate(int i){
if(i<n){
lazy[i<<1]=Operator::op(lazy[i<<1],lazy[i]);
lazy[i<<1|1]=Operator::op(lazy[i<<1|1],lazy[i]);
dat[i<<1]=mapping(dat[i<<1],lazy[i]);
dat[i<<1|1]=mapping(dat[i<<1|1],lazy[i]);
}
lazy[i]=Operator::id();
}
void pushdown(){
for(int j=(int)indices.size()-1;j>=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<typename T,T max_value=INF>
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<typename T,T min_value=-INF>
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<typename T>
struct Sum{
using Type=T;
static Type id(){return 0;}
static Type op(const Type&a,const Type&b){return a+b;}
};
/// @brief (和,区間の長さ)
template<typename T>
struct SumPair{
using Type=pair<T,int>;
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<typename T,T not_exist>
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<typename T>
struct Add{
using Type=T;
static Type id(){return 0;}
static Type op(const Type&a,const Type&b){return a+b;}
};
template<typename T>
struct UpdateTimeStamp{
using Type=pair<T,int>;
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<typename T,T max_value,T not_exist>
struct Update_GetMin{
static T mapping(const T&a,const T&b){return b==not_exist?a:b;}
using Type=struct SegTreeLazy<Monoid::Min<T,max_value>,Operator::Update<T,not_exist>,mapping>;
};
template<typename T,T min_value,T not_exist>
struct Update_GetMax{
static T mapping(const T&a,const T&b){return b==not_exist?a:b;}
using Type=struct SegTreeLazy<Monoid::Max<T,min_value>,Operator::Update<T,not_exist>,mapping>;
};
template<typename T,T not_exist>
struct Update_GetSum{
using S=typename Monoid::SumPair<T>::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<Monoid::SumPair<T>,Operator::Update<T,not_exist>,mapping>;
};
template<typename T,T max_value>
struct Add_GetMin{
static T mapping(const T&a,const T&b){return a+b;}
using Type=struct SegTreeLazy<Monoid::Min<T,max_value>,Operator::Add<T>,mapping>;
};
template<typename T,T min_value>
struct Add_GetMax{
static T mapping(const T&a,const T&b){return a+b;}
using Type=struct SegTreeLazy<Monoid::Max<T,min_value>,Operator::Add<T>,mapping>;
};
template<typename T>
struct Add_GetSum{
using S=typename Monoid::SumPair<T>::Type;
static S mapping(const S&a,const T&b){return{a.first+b*a.second,a.second};}
using Type=struct SegTreeLazy<Monoid::SumPair<T>,Operator::Add<T>,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<r.minval){
return l;
}else{
return r;
}
}
static Type id(){
return {INF,0};
}
};
struct Ope{
using Type=int;
static Type op(int l,int r){
return l+r;
}
static Type id(){
return 0;
}
};
Info mapping(Info x,int f){
x.minval+=f;
return x;
}
int main(){
IO;
int N;cin>>N;
vector<Info>init(N,Info());
SegTreeLazy<Mono,Ope,mapping>seg(init);
int Q;cin>>Q;
vector<pair<int,int>>query(Q);
for(int q=0;q<Q;q++){
int t;cin>>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<<ans<<'\n';
}
}
}
Today03