結果
問題 | No.833 かっこいい電車 |
ユーザー | 👑 Kazun |
提出日時 | 2021-03-13 04:24:10 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 701 ms / 2,000 ms |
コード長 | 8,836 bytes |
コンパイル時間 | 167 ms |
コンパイル使用メモリ | 82,688 KB |
実行使用メモリ | 114,048 KB |
最終ジャッジ日時 | 2024-10-14 16:55:07 |
合計ジャッジ時間 | 13,042 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 378 ms
93,568 KB |
testcase_01 | AC | 44 ms
54,784 KB |
testcase_02 | AC | 43 ms
54,528 KB |
testcase_03 | AC | 42 ms
54,656 KB |
testcase_04 | AC | 42 ms
54,144 KB |
testcase_05 | AC | 43 ms
54,784 KB |
testcase_06 | AC | 41 ms
53,888 KB |
testcase_07 | AC | 43 ms
54,528 KB |
testcase_08 | AC | 42 ms
54,016 KB |
testcase_09 | AC | 41 ms
54,272 KB |
testcase_10 | AC | 526 ms
94,720 KB |
testcase_11 | AC | 562 ms
110,208 KB |
testcase_12 | AC | 350 ms
91,648 KB |
testcase_13 | AC | 357 ms
81,940 KB |
testcase_14 | AC | 516 ms
111,744 KB |
testcase_15 | AC | 361 ms
93,696 KB |
testcase_16 | AC | 244 ms
97,920 KB |
testcase_17 | AC | 538 ms
84,964 KB |
testcase_18 | AC | 651 ms
94,976 KB |
testcase_19 | AC | 253 ms
95,232 KB |
testcase_20 | AC | 108 ms
83,328 KB |
testcase_21 | AC | 701 ms
90,688 KB |
testcase_22 | AC | 335 ms
112,384 KB |
testcase_23 | AC | 292 ms
96,128 KB |
testcase_24 | AC | 366 ms
112,256 KB |
testcase_25 | AC | 658 ms
93,440 KB |
testcase_26 | AC | 299 ms
108,672 KB |
testcase_27 | AC | 465 ms
94,976 KB |
testcase_28 | AC | 490 ms
85,992 KB |
testcase_29 | AC | 452 ms
92,928 KB |
testcase_30 | AC | 624 ms
114,048 KB |
testcase_31 | AC | 357 ms
93,440 KB |
ソースコード
class Lazy_Evaluation_Tree(): def __init__(self,L,calc,unit,op,comp,id,index): """calcを演算,opを作用とするリストLのSegment Treeを作成 calc:演算 unit:モノイドcalcの単位元 (xe=ex=xを満たすe) op:作用素 comp:作用素の合成 id:恒等写像 [条件] M:Monoid,F={f:F x M→ M:作用素}に対して,以下が成立する. Fは恒等写像 id を含む.つまり,任意の x in M に対して id(x)=x Fは写像の合成に閉じている.つまり,任意の f,g in F に対して, comp(f,g) in F 任意の f in F, x,y in M に対して,f(xy)=f(x)f(y)である. [注記] 作用素は左から掛ける.更新も左から. """ self.calc=calc self.unit=unit self.op=op self.comp=comp self.id=id self.index=index N=len(L) d=max(1,(N-1).bit_length()) k=1<<d self.data=[unit]*k+L+[unit]*(k-len(L)) self.lazy=[self.id]*(2*k) self.N=k self.depth=d for i in range(k-1,0,-1): self.data[i]=calc(self.data[i<<1],self.data[i<<1|1]) def _eval_at(self,m): if self.lazy[m]==self.id: return self.data[m] return self.op(self.lazy[m],self.data[m]) #配列の第m要素を下に伝搬 def _propagate_at(self,m): self.data[m]=self._eval_at(m) if m<self.N and self.lazy[m]!=self.id: self.lazy[m<<1]=self.comp( self.lazy[m], self.lazy[m<<1] ) self.lazy[m<<1|1]=self.comp( self.lazy[m], self.lazy[m<<1|1] ) self.lazy[m]=self.id #配列の第m要素より上を全て伝搬 def _propagate_above(self,m): H=m.bit_length() for h in range(H-1,0,-1): self._propagate_at(m>>h) #配列の第m要素より上を全て再計算 def _recalc_above(self,m): while m>1: m>>=1 self.data[m]=self.calc( self._eval_at(m<<1), self._eval_at(m<<1|1) ) def get(self,k): index=self.index m=k-index+self.N self._propagate_above(m) self.data[m]=self._eval_at(m) self.lazy[m]=self.id return self.data[m] #作用 def operate(self,From,To,alpha,left_closed=True,right_closed=True): index=self.index L=(From-index)+self.N+(not left_closed) R=(To-index)+self.N+(right_closed) L0=R0=-1 X,Y=L,R-1 while X<Y: if X&1: L0=max(L0,X) X+=1 if Y&1==0: R0=max(R0,Y) Y-=1 X>>=1 Y>>=1 L0=max(L0,X) R0=max(R0,Y) self._propagate_above(L0) self._propagate_above(R0) while L<R: if L&1: self.lazy[L]=self.comp(alpha,self.lazy[L]) L+=1 if R&1: R-=1 self.lazy[R]=self.comp(alpha,self.lazy[R]) L>>=1 R>>=1 self._recalc_above(L0) self._recalc_above(R0) def update(self,k,x): """ 第k要素をxに変更する. """ index=self.index m=k-index+self.N self._propagate_above(m) self.data[m]=x self.lazy[m]=self.id self._recalc_above(m) def product(self,From,To,left_closed=True,right_closed=True): index=self.index L=(From-index)+self.N+(not left_closed) R=(To-index)+self.N+(right_closed) L0=R0=-1 X,Y=L,R-1 while X<Y: if X&1: L0=max(L0,X) X+=1 if Y&1==0: R0=max(R0,Y) Y-=1 X>>=1 Y>>=1 L0=max(L0,X) R0=max(R0,Y) self._propagate_above(L0) self._propagate_above(R0) vL=vR=self.unit while L<R: if L&1: vL=self.calc(vL,self._eval_at(L)) L+=1 if R&1: R-=1 vR=self.calc(self._eval_at(R),vR) L>>=1 R>>=1 return self.calc(vL,vR) def all_product(self): return self.product(1,self.N,1) #リフレッシュ def refresh(self): for m in range(1,2*self.N): self.data[m]=self._eval_at(m) if m<self.N and self.lazy[m]!=self.id: self.lazy[m<<1]=self.comp( self.lazy[m], self.lazy[m<<1] ) self.lazy[m<<1|1]=self.comp( self.lazy[m], self.lazy[m<<1|1] ) self.lazy[m]=self.id def __getitem__(self,k): return self.get(k) def __setitem__(self,k,x): self.update(k,x) class Binary_Indexed_Tree(): def __init__(self,L,calc,unit,inv,index=1): """calcを演算とするN項のBinary Indexed Treeを作成 calc:演算(2変数関数,群) unit:群calcの単位元(xe=ex=xを満たすe) inv:群calcの逆元(1変数関数) """ self.calc=calc self.unit=unit self.inv=inv self.index=index N=len(L) d=max(1,(N-1).bit_length()) k=2**d X=[None]+[unit]*k self.num=k self.depth=d if L: for i in range(len(L)): p=i+1 while p<=k: X[p]=self.calc(X[p],L[i]) p+=p&(-p) self.data=X def index_number(self,k,index=1): """第k要素の値を出力する. k:数列の要素 index:先頭の要素の番号 """ return self.sum(k,k,index) def add(self,k,x,index=1,right=False): """第k要素にxを左から加え,更新を行う. k:数列の要素 x:更新後の値 index:先頭の要素の番号 right:「左から」が「右から」になる """ p=k+(1-index) while p<=self.num: if right==False: #左から self.data[p]=self.calc(x,self.data[p]) else: #右から self.data[p]=self.calc(self.data[p],x) p+=p&(-p) def update(self,k,x,index=1,right=False): """第k要素をxに変え,更新を行う. k:数列の要素 x:更新後の値 """ a=self.index_number(k,index) if right==False: #左から y=self.calc(x,self.inv(a)) else: #右から y=self.calc(self.inv(a),x) self.add(k,y,index,right) def sum(self,From,To,index=1): """第From要素から第To要素までの総和を求める. ※From!=1を使うならば,群でなくてはならない. From:始まり To:終わり index:先頭の要素の番号 """ alpha=max(1,From+(1-index)) beta=min(self.num,To+(1-index)) if alpha==1: return self.__section(beta) else: return self.calc(self.inv(self.__section(alpha-1)),self.__section(beta)) def __section(self,To): S=self.unit x=To while x>0: S=self.calc(self.data[x],S) x-=x&(-x) return S def all_sum(self): return self.data[-1] def __getitem__(self,index): if isinstance(index,int): return self.index_number(index,self.index) else: return [self.index_number(t,self.index) for t in index] def __setitem__(self,index,val): self.update(index,val,self.index) #================================================ import sys from operator import add,neg input=sys.stdin.readline write=sys.stdout.write N,Q=map(int,input().split()) A=list(map(int,input().split())) L=Lazy_Evaluation_Tree(list(range(1,N+1)),max,0,lambda a,x:a,lambda a,b:a,-1,1) R=Lazy_Evaluation_Tree(list(range(1,N+1)),max,0,lambda a,x:a,lambda a,b:a,-1,1) S=Binary_Indexed_Tree(A,add,0,neg,1) X=[] Connect=[0]*N for _ in range(Q): t,x=map(int,input().split()) if t==1: if Connect[x]==0: l=L.get(x) r=R.get(x+1) L.operate(l,r,l) R.operate(l,r,r) Connect[x]=1 elif t==2: if Connect[x]==1: l=L.get(x) r=R.get(x+1) R.operate(l,x,x) L.operate(x+1,r,x+1) Connect[x]=0 elif t==3: S.add(x,1,1) else: l=L.get(x) r=R.get(x) X.append(S.sum(l,r,1)) write("\n".join(map(str,X)))