結果
| 問題 |
No.2308 [Cherry 5th Tune B] もしかして、真?
|
| コンテスト | |
| ユーザー |
navel_tos
|
| 提出日時 | 2023-05-19 23:14:03 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,485 bytes |
| コンパイル時間 | 401 ms |
| コンパイル使用メモリ | 82,436 KB |
| 実行使用メモリ | 266,328 KB |
| 最終ジャッジ日時 | 2024-12-20 01:45:36 |
| 合計ジャッジ時間 | 84,467 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 6 WA * 5 TLE * 28 |
ソースコード
#yukicoder389D
'''
■考察欄
しんどそうな問題だなぁ。
T/F と 論理演算子を与える。
すげ替えを行うので、論理演算結果が最終的にどうなるか示せ。
愚直にやると、間に合わないか?
impがややこしいな。
T→T : T
T→F : F
F→T : T
F→F : T
dequeみたいなデータ構造があると楽なんだが、そんなものはない。
対決順を定められたらなぁ。
本当にやりたくないですがクエリ平方分割してやります。
区間を√N個に分割し、愚直に論理演算をやります。
区間をまたぐときが怖いから、追加ルールとして
「演算結果は左側に格納する」というものを用意しよう。
っていうか、残っている演算子の数さえわかればいいのでは?
「左からx番目の演算子はなんですか」が分かればいいなら、それはもうセグ木でいける。
'''
#Segment Tree: O(logN)
class SegmentTree:
def __init__(self,n,identity_e,combine_f):
self._n=n;self._size=1
while self._size<self._n:self._size<<=1
self._identity_e=identity_e;self._combine_f=combine_f;self._node=[self._identity_e]*2*self._size
def build(self,array):
assert len(array)==self._n,'array too large'
for i,v in enumerate(array,start=self._size):self._node[i]=v
for i in range(self._size-1,0,-1):self._node[i]=self._combine_f(self._node[i<<1|0],self._node[i<<1|1])
def update(self,index,value): #一点更新
i=self._size+index;self._node[i]=value
while i-1:i>>=1;self._node[i]=self._combine_f(self._node[i<<1|0],self._node[i<<1|1])
def fold(self,L,R): #区間取得: [L,R)の区間値を得る
L+=self._size;R+=self._size;vL,vR=[self._identity_e]*2
while L<R:
if L&1:vL=self._combine_f(vL,self._node[L]);L+=1
if R&1:R-=1;vR=self._combine_f(self._node[R],vR)
L>>=1;R>>=1
return self._combine_f(vL,vR)
from collections import defaultdict as dd
add=lambda x,y:x+y
for _ in range(int(input())):
N=int(input()); X=list(map(lambda x: x=='True',input().split())); Y=input().split()
S=list(map(int,input().split()))
ST=SegmentTree(N,0,add); ST.build([1]*N)
for i in S: #左からi番目の真偽値と、i+1番目の真偽値を特定せよ。
#1. 左からi番目の真偽値のインデックスを特定する
#[0,x) の中に、まだ計算されていない真偽値がちょうどi-1個で、
#[0,x+1) だと、真偽値がちょうどi個になる。
#ok: 真偽値がi個未満、ng: 真偽値がi個以上 で判定しよう。
ok,ng=0,N #[0,x)に真偽値がいくつあるか?
while abs(ok-ng)>1:
mid=(ok+ng)//2; now=ST.fold(0,mid)
(ok,ng)=(mid,ng) if now<i else (ok,mid)
Lt=ok; ng=N
#次に、[0,x)の中に真偽値がi+1個あるものを探す
while abs(ok-ng)>1:
mid=(ok+ng)//2; now=ST.fold(0,mid)
(ok,ng)=(mid,ng) if now<i+1 else (ok,mid)
Rt=ok
#LtとRtの真偽値を合成し、Rt側に格納する
ope=Y[Rt-1]
if ope=='and': end=(X[Lt] and X[Rt])
if ope=='or': end=(X[Lt] or X[Rt])
if ope=='xor': end=(X[Lt]^X[Rt])
if ope=='imp':
if X[Lt]==True and X[Rt]==False: end=False
else: end=True
X[Rt]=end; ST.update(Lt,0)
print(end)
navel_tos