#![allow(non_snake_case)] fn main(){ proconio::input!{ n:usize, a:[usize;n], } // naive(n,&a); use std::collections::*; let mut set=(0..n).map(|i|(i,a[i])).collect::>(); let mut perm=vec![!0;n]; let mut que=(0..n).filter(|&i|a[i]==0).collect::>(); let mut it=0..; while let Some(i)=que.pop(){ let &(ci,val)=set.range((i,0)..).next().unwrap(); assert!(i==ci); perm[i]=it.next().unwrap(); set.remove(&(i,val)); macro_rules! update{ ($ni:expr,$val:expr)=>{ set.remove(&($ni,$val)); if $val==0{ println!("0"); return; } set.insert(($ni,$val-1)); if $val==1{ que.push($ni); } } } if let Some(&(ni,val))=set.range((i,0)..).next(){ update!(ni,val); } if let Some(&(ni,val))=set.range(..(i,0)).rev().next(){ update!(ni,val); } } if !set.is_empty(){ println!("0"); return; } // impl_monoid!(Max,(usize,usize),(0,0),|a:(usize,usize),b:(usize,usize)|a.max(b)); // let seg=Segtree::::from((0..n).map(|i|(perm[i],i)).collect::>()); type M=ModInt998244353; let pre=Pre::::new(n); fn rec(perm:&[usize],l:usize,r:usize,pre:&Pre)->M{ if l==r{ M::new(1) } else{ let mi=(l..r).max_by_key(|&i|perm[i]).unwrap(); pre.choose(r-l-1,mi-l)*rec(perm,l,mi,pre)*rec(perm,mi+1,r,pre) } } let ans=rec(&perm,0,n,&pre); println!("{ans}"); } // fn naive(n:usize,a:&[usize]){ // use itertools::*; // let mut ans=0; // for is in (0..n).permutations(n){ // let mut b=vec![!0;n]; // for &i in &is{ // b[i]=0; // if let Some(ni)=(0..i).rev().find(|&ni|b[ni]!=!0){ // b[ni]+=1; // } // if let Some(ni)=(i+1..n).find(|&ni|b[ni]!=!0){ // b[ni]+=1; // } // } // if a==b{ // ans+=(a==&b) as usize; // } // } // eprintln!("#{ans}"); // } #[derive(Clone)] struct Segtree{ n:usize, size:usize, a:Vec, } impl From> for Segtree{ fn from(v:Vec)->Self{ let n=v.len(); let size=n.next_power_of_two(); let mut a=vec![M::e();size*2]; a[size..size+n].copy_from_slice(&v); for i in (1..size).rev(){ a[i]=M::op(a[i*2],a[i*2+1]); } Segtree{n,size,a} } } impl Segtree{ fn new(n:usize)->Self{ let size=n.next_power_of_two(); Segtree{ n,size, a:vec![M::e();size*2], } } fn set(&mut self,mut i:usize,v:M::S){ assert!(iM::S{ assert!(i)->M::S{ use std::ops::Bound::*; let mut u=match range.start_bound(){ Included(&a)=>a, Excluded(&a)=>a+1, Unbounded=>0, }; let mut v=match range.end_bound(){ Included(&a)=>a+1, Excluded(&a)=>a, Unbounded=>self.n, }; assert!(u<=v && v<=self.n); if (u,v)==(0,self.n){ return self.a[1]; } let mut um=M::e(); let mut vm=M::e(); u+=self.size; v+=self.size; while ubool)->usize{ assert!(l<=self.n && f(M::e())); if l==self.n{ return self.n; } l+=self.size; let mut m=M::e(); loop{ l>>=l.trailing_zeros(); if !f(M::op(m,self.a[l])){ while lbool)->usize{ assert!(r<=self.n && f(M::e())); if r==0{ return 0; } r+=self.size; let mut m=M::e(); loop{ r-=1; r>>=r.trailing_ones(); r=r.max(1); if !f(M::op(self.a[r],m)){ while rSelf::S; fn op(left:Self::S,right:Self::S)->Self::S; } #[macro_export] macro_rules! impl_monoid{ ($t:ident,$item:ty,$e:expr,$op:expr)=>{ #[derive(Clone,Copy)] struct $t(); impl Monoid for $t{ type S=$item; fn e()->$item{ $e } fn op(left:$item,right:$item)->$item{ $op(left,right) } } }; } type ModInt998244353=ModInt<998244353>; type ModInt1000000007=ModInt<1000000007>; #[derive(Clone,Copy,PartialEq,Eq,Default,Hash)] struct ModInt(u32); impl ModIntBase for ModInt{ fn modulus()->u32{ MOD } fn val(self)->u32{ self.0 } fn new(v:impl RemU32)->Self{ Self(v.rem_u32(MOD)) } fn inv(self)->Self{ assert!(self.0!=0); let (mut a,mut b)=(self.0 as i64,MOD as i64); let (mut u,mut v)=(1,0); while b!=0{ let t=a/b; (a,b)=(b,a-t*b); (u,v)=(v,u-t*v); } assert!(a==1); if u<0{ u+=MOD as i64; } Self(u as u32) } fn pow(self,mut k:u64)->Self{ let mut pow2=self; let mut ret=Self(1); while k>0{ if k&1==1{ ret*=pow2; } pow2*=pow2; k>>=1; } ret } } impl std::fmt::Display for ModInt{ fn fmt(&self,f:&mut std::fmt::Formatter)->std::fmt::Result{ write!(f,"{}",self.0) } } impl std::fmt::Debug for ModInt{ fn fmt(&self,f:&mut std::fmt::Formatter)->std::fmt::Result{ write!(f,"{}",self.0) } } impl std::ops::Add for ModInt{ type Output=Self; fn add(self,a:Self)->Self{ let mut new=self.0+a.0; if MOD<=new{ new-=MOD; } Self(new) } } impl std::ops::Sub for ModInt{ type Output=Self; fn sub(self,a:Self)->Self{ let mut new=self.0-a.0; if 0>new as i32{ new+=MOD; } Self(new) } } impl std::ops::Mul for ModInt{ type Output=Self; fn mul(self,a:Self)->Self{ Self((self.0 as u64*a.0 as u64%MOD as u64) as u32) } } impl std::ops::Div for ModInt{ type Output=Self; fn div(self,a:Self)->Self{ self*a.inv() } } impl std::ops::Neg for ModInt{ type Output=Self; fn neg(self)->Self{ if self.0==0{ return self; } Self(MOD-self.0) } } impl std::str::FromStr for ModInt{ type Err=::Err; fn from_str(s:&str)->Result{ let x=s.parse::()?; Ok(Self::new(x)) } } macro_rules! impl_modint_ops{ ($trait:ident,$func:ident,$assign_trait:ident,$assign_func:ident,$op:tt)=>{ impl std::ops::$assign_trait for ModInt{ fn $assign_func(&mut self,a:Self){ *self=*self $op a } } impl std::ops::$trait for ModInt{ type Output=Self; fn $func(self,a:T)->Self{ self $op Self::new(a) } } impl std::ops::$assign_trait for ModInt{ fn $assign_func(&mut self,a:T){ *self=*self $op Self::new(a) } } } } impl_modint_ops!(Add,add,AddAssign,add_assign,+); impl_modint_ops!(Sub,sub,SubAssign,sub_assign,-); impl_modint_ops!(Mul,mul,MulAssign,mul_assign,*); impl_modint_ops!(Div,div,DivAssign,div_assign,/); impl std::iter::Sum for ModInt{ fn sum>(iter:I)->Self{ iter.fold(Self(0),|sum,x|sum+x) } } impl std::iter::Product for ModInt{ fn product>(iter:I)->Self{ iter.fold(Self(1),|prod,x|prod*x) } } trait RemU32{ fn rem_u32(self,m:u32)->u32; } macro_rules! impl_rem_u32{ ($($ty:tt),*)=>{ $( impl RemU32 for $ty{ fn rem_u32(self,m:u32)->u32{ (self as i64).rem_euclid(m as i64) as _ } } )* } } impl_rem_u32!(i32,i64); macro_rules! impl_rem_u32{ ($($ty:tt),*)=>{ $( impl RemU32 for $ty{ fn rem_u32(self,m:u32)->u32{ (self%(m as $ty)) as _ } } )* } } impl_rem_u32!(u32,u64,usize); trait ModIntBase:Default+std::str::FromStr+Copy+Eq+std::hash::Hash+std::fmt::Display+std::fmt::Debug +std::ops::Neg+std::ops::Add+std::ops::Sub +std::ops::Mul+std::ops::Div +std::ops::AddAssign+std::ops::SubAssign+std::ops::MulAssign+std::ops::DivAssign { fn modulus()->u32; fn val(self)->u32; fn new(v:impl RemU32)->Self; fn inv(self)->Self; fn pow(self,k:u64)->Self; } // Modを超える数はpanicする // 注意: // Modは素数 // multi_choose(n,k)を使うときは,fac(n+k-1)まで必要になる struct Pre{ fac:Vec, finv:Vec, } impl Pre{ fn new(n:usize)->Self{ assert!(nM{ self.fac[n] } fn finv(&self,n:usize)->M{ self.finv[n] } fn inv(&self,n:usize)->M{ assert!(n!=0); self.finv[n]*self.fac[n-1] } fn perm(&self,n:usize,k:usize)->M{ if nM{ if nM{ if (n as i64)<0 || (k as i64)<0{ return M::new(0); } if n==0 && k==0{ return M::new(1); } self.choose(n+k-1,k) } }