結果

問題 No.703 ゴミ拾い Easy
ユーザー vwxyz
提出日時 2024-11-20 17:49:06
言語 PyPy3
(7.3.15)
結果
RE  
実行時間 -
コード長 16,487 bytes
コンパイル時間 493 ms
コンパイル使用メモリ 82,048 KB
実行使用メモリ 178,484 KB
最終ジャッジ日時 2024-11-20 17:49:18
合計ジャッジ時間 11,032 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 24 RE * 22
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

import sys
readline=sys.stdin.readline
class AVLTree_dict:
def __init__(self):
self.root=None
self.parent=[]
self.key=[]
self.value=[]
self.left=[]
self.right=[]
self.bias=[]
self.size=[]
def Make_Node(self,parent,key,value):
retu=len(self.parent)
self.parent.append(parent)
self.key.append(key)
self.value.append(value)
self.left.append(None)
self.right.append(None)
self.bias.append(0)
self.size.append(1)
return retu
def Rotate_Left(self,node):
node_right=self.right[node]
self.size[node_right]-self.size[node]
self.size[node]-=1
if node_right<len(self.righr) and self.right[node_right]!=None:
self.size[node]-=self.size[self.right[node_right]]
if self.bias[node_right]==-1:
self.bias[node_right]=0
self.bias[node]=0
else:
#assert node_right.bias==0
self.bias[node_right]=1
self.bias[node]=-1
self.right[node]=self.left[node_right]
self.left[node_right]=node
return node_right
def Rotate_Right(self,node):
node_left=self.left[node]
self.size[node_left]=self.size[node]
self.size[node]-=1
if node_left<len(self.left) and self.left[node_left]!=None:
self.size[node]-=self.size[self.left[node_left]]
if self.bias[node_left]==1:
self.bias[node_left]=0
self.bias[node]=0
else:
#assert node_left.bias==0
self.bias[node_left]=-1
self.bias[node_left]=-1
self.bias[node]=1
self.left[node]=self.right[node_left]
self.right[node_left]=node
return node_left
def Rotate_Left_Right(self,node):
node_left=self.left[node]
node_left_right=self.right[node_left]
#assert node.bias==2
#assert node_left.bias==-1
#assert node_left_right.bias in (-1,0,1)
self.size[node_left_right]=self.size[node]
self.size[node]-=self.size[node_left]
if node_left_right<len(self.right) and self.right[node_left_right]!=None:
self.size[node]+=self.size[self.right[node_left_right]]
self.size[node_left]-=1
if node_left_right<len(self.right) and self.right[node_left_right]!=None:
self.size[node_left]-=self.size[self.right[node_left_right]]
self.right[node_left]=self.left[node_left_right]
self.left[node_left_right]=node_left
self.left[node]=self.right[node_left_right]
self.right[node_left_right]=node
self.Update_Bias_Double(node_left_right)
return node_left_right
def Rotate_Right_Left(self,node):
node_right=self.right[node]
node_right_left=self.left[node_right]
#assert node.bias==-2
#assert node_right.bias==1
#assert node_right_left.bias in (-1,0,1)
self.size[node_right_left]=self.size[node]
self.size[node]-=self.size[node_right]
if node_right_left<len(self.left) and self.left[node_right_left]!=None:
self.size[node]+=self.size[self.left[node_right_left]]
self.size[node_right]-=1
if node_right_left<len(self.left) and self.left[node_right_left]!=None:
self.size[node_right]-=self.size[self.left[node_right_left]]
self.left[node_right]=self.right[node_right_left]
self.right[node_right_left]=node_right
self.right[node]=self.left[node_right_left]
self.left[node_right_left]=node
self.Update_Bias_Double(node_right_left)
return node_right_left
def Update_Bias_Double(self,node):
#assert node.right.bias*node.left.bias==-2
#assert node.right.bias>0
if self.bias[node]==1:
self.bias[self.right[node]]=-1
self.bias[self.left[node]]=0
elif self.bias[node]==-1:
self.bias[self.right[node]]=0
self.bias[self.left[node]]=1
else:
self.bias[self.right[node]]=0
self.bias[self.left[node]]=0
self.bias[node]=0
def __getitem__(self,key):
v=self.root
while v!=None:
if key<self.key[v]:
v=self.left[v]
elif self.key[v]<key:
v=self.right[v]
else:
return self.value[v]
return None
def __setitem__(self,key,value):
if self.root==None:
self.root=self.Make_Node(None,key,value)
return
v=self.root
stack=[]
while v!=None:
if key<self.key[v]:
stack.append((v,1))
v=self.left[v]
elif self.key[v]<key:
stack.append((v,-1))
v=self.right[v]
elif self.key[v]==key:
self.value[v]=value
return
p,direction=stack[-1]
if direction==1:
self.left[p]=self.Make_Node(p,key,value)
else:
self.right[p]=self.Make_Node(p,key,value)
while stack:
v,direction=stack.pop()
self.bias[v]+=direction
self.size[v]+=1
vv=None
if self.bias[v]==2:
if self.bias[self.left[v]]==-1:
vv=self.Rotate_Left_Right(v)
else:
vv=self.Rotate_Right(v)
#assert vv!=None
break
if self.bias[v]==-2:
if self.bias[self.right[v]]==1:
vv=self.Rotate_Right_Left(v)
else:
vv=self.Rotate_Left(v)
#assert vv!=None
break
if self.bias[v]==0:
break
if vv!=None:
if len(stack)==0:
self.root=vv
return
p,direction=stack.pop()
self.size[p]+=1
if direction==1:
self.left[p]=vv
else:
self.right[p]=vv
while stack:
p,direction=stack.pop()
self.size[p]+=1
def __delitem__(self,key):
v=self.root
stack=[]
while v!=None:
if key<self.key[v]:
stack.append((v,1))
v=self.left[v]
elif self.key[v]<key:
stack.append((v,-1))
v=self.right[v]
else:
break
else:
return False
if v<len(self.left) and self.left[v]!=None:
stack.append((v,1))
lmax=self.left[v]
while lmax<len(self.right) and self.right[lmax]!=None:
stack.append((lmax,-1))
lmax=self.right[lmax]
self.key[v]=self.key[lmax]
self.value[v]=self.value[lmax]
v=lmax
c=self.right[v] if self.left[v]==None else self.left[v]
if stack:
p,direction=stack[-1]
if direction==1:
self.left[p]=c
else:
self.right[p]=c
else:
self.root=c
return True
while stack:
pp=None
p,direction=stack.pop()
self.bias[p]-=direction
self.size[p]-=1
if self.bias[p]==2:
if self.bias[self.left[p]]==-1:
pp=self.Rotate_Left_Right(p)
else:
pp=self.Rotate_Right(p)
elif self.bias[p]==-2:
if self.bias[self.right[p]]==1:
pp=self.Rotate_Right_Left(p)
else:
pp=self.Rotate_Left(p)
elif self.bias[p]!=0:
break
if pp!=None:
if len(stack)==0:
self.root=pp
return True
p,direction=stack[-1]
if direction==1:
self.left[p]=pp
else:
self.right[p]=pp
if self.bias[pp]!=0:
break
while stack:
p,direction=stack.pop()
self.size[p]-=1
return True
def __contains__(self,key):
v=self.root
while v!=None:
if key<self.key[v]:
v=self.left[v]
elif self.key[v]<key:
v=self.right[v]
else:
return True
return False
def Bisect_Right(self,key):
retu=None
v=self.root
while v!=None:
if self.key[v]>key:
if retu==None or retu[0]>self.key[v]:
retu=(self.key[v],self.value[v])
v=self.left[v]
else:
v=self.right[v]
return retu
def Bisect_Left(self,key):
retu=None
v=self.root
while v!=None:
if self.key[v]<key:
if retu==None or retu[0]<self.key[v]:
retu=(self.key[v],self.value[v])
v=self.right[v]
else:
v=self.left[v]
return retu
def Find_Kth_Element(self,K):
v=self.root
s=0
while v!=None:
t=s+self.size[self.left[v]] if v<len(self.left) and self.left[v]!=None else s
if t==K:
return self.key[v],self.value[v]
elif t<K:
s=t+1
v=self.right[v]
else:
v=self.left[v]
return None
def keys(self):
stack=[(self.root,True)]
while stack:
node,subtree=stack.pop()
if subtree:
if node<len(self.right) and self.right[node]!=None:
stack.append((self.right[node],True))
stack.append((node,False))
if node<len(self.left) and self.left[node]!=None:
stack.append((self.left[node],True))
else:
yield self.key[node]
def values(self):
stack=[(self.root,True)]
while stack:
node,subtree=stack.pop()
if subtree:
if node<len(self.right) and self.right[node]!=None:
stack.append((self.right[node],True))
stack.append((node,False))
if node<len(self.left) and self.left[node]!=None:
stack.append((self.left[node],True))
else:
yield self.value[node]
def items(self):
stack=[(self.root,True)]
while stack:
node,subtree=stack.pop()
if subtree:
if node<len(self.right) and self.right[node]!=None:
stack.append((self.right[node],True))
stack.append((node,False))
if node<len(self.left) and self.left[node]!=None:
stack.append((self.left[node],True))
else:
yield (self.key[node],self.value[node])
def __bool__(self):
return self.root!=None
def __len__(self):
return 0 if self.root==None else self.size[self.root]
def __iter__(self):
return iter(self.keys())
def __str__(self):
if self.root==None:
retu="{}"
else:
retu="{"+", ".join(f"{r}: {m}" for r,m in self.items())+"}"
return retu
class Convex_Hull_Trick:
def __init__(self,avl=False):
self.avl=avl
if self.avl:
self.lines=AVLTree_dict()
else:
self.lines_A=SortedSet()
self.lines_B={}
def is_removed(self,line0,line1,line2):
if line0==None:
return False
if line2==None:
return False
a0,b0=line0
a1,b1=line1
a2,b2=line2
return (a1-a0)*(b2-b1)<=(b1-b0)*(a2-a1)
def add_line(self,a,b):
if self.avl:
bb=self.lines[a]
else:
if a in self.lines_B:
bb=self.lines_B[a]
else:
bb=None
if bb!=None and bb<=b:
return
if self.avl:
line0=self.lines.Bisect_Left(a)
else:
aa=self.lines_A.lt(a)
if aa==None:
line0=None
else:
line0=(aa,self.lines_B[aa])
line1=(a,b)
if self.avl:
line2=self.lines.Bisect_Right(a)
else:
aa=self.lines_A.gt(a)
if aa==None:
line2=None
else:
line2=(aa,self.lines_B[aa])
if self.is_removed(line0,line1,line2):
return
if self.avl:
self.lines[a]=b
else:
self.lines_A.add(a)
self.lines_B[a]=b
line2=(a,b)
if self.avl:
line1=self.lines.Bisect_Left(line2[0])
line0=None if line1==None else self.lines.Bisect_Left(line1[0])
else:
aa=self.lines_A.lt(line2[0])
if aa==None:
line1=None
else:
line1=(aa,self.lines_B[aa])
if line1==None:
line0=None
else:
aa=self.lines_A.lt(line1[0])
if aa==None:
line0=None
else:
line0=(aa,self.lines_B[aa])
while self.is_removed(line0,line1,line2):
if self.avl:
del self.lines[line1[0]]
else:
assert self.lines_A.discard(line1[0])
del self.lines_B[line1[0]]
line1=line0
if self.avl:
line0=None if line1==None else self.lines.Bisect_Left(line1[0])
else:
aa=self.lines_A.lt(line1[0])
if aa==None:
line0=None
else:
line0=(aa,self.lines_B[aa])
line0=(a,b)
if self.avl:
line1=self.lines.Bisect_Right(line0[0])
line2=None if line1==None else self.lines.Bisect_Right(line1[0])
else:
aa=self.lines_A.gt(line0[0])
if aa==None:
line1=None
else:
line1=(aa,self.lines_B[aa])
if line1==None:
line2=None
else:
aa=self.lines_A.gt(line1[0])
if aa==None:
line2=None
else:
line2=(aa,self.lines_B[aa])
while self.is_removed(line0,line1,line2):
if self.avl:
del self.lines[line1[0]]
else:
assert self.lines_A.discard(line1[0])
del self.lines_B[line1[0]]
line1=line2
if self.avl:
line2=None if line1==None else self.lines.Bisect_Right(line1[0])
else:
aa=self.lines_A.gt(line1[0])
if aa==None:
line2=None
else:
line2=(aa,self.lines_B[aa])
def __call__(self,x):
if self.avl:
size=len(self.lines)
else:
size=len(self.lines_A)
if not size:
return None
ok,ng=-1,size-1
while ng-ok>1:
mid=(ok+ng)//2
if self.avl:
a0,b0=self.lines.Find_Kth_Element(mid)
a1,b1=self.lines.Find_Kth_Element(mid+1)
else:
a0=self.lines_A[mid]
b0=self.lines_B[a0]
a1=self.lines_A[mid+1]
b1=self.lines_B[a1]
if a0*x+b0>a1*x+b1:
ok=mid
else:
ng=mid
if self.avl:
a,b=self.lines.Find_Kth_Element(ok+1)
else:
a=self.lines_A[ok+1]
b=self.lines_B[a]
return a*x+b
def __getitem__(self,a):
if self.avl:
return self.lines[a]
else:
if a in self.lines_A:
return self.lines_B[a]
else:
return None
def __setitem__(self,a,b):
self.add_line(a,b)
N=int(readline())
A=list(map(int,readline().split()))
X=list(map(int,readline().split()))
Y=list(map(int,readline().split()))
dp=Convex_Hull_Trick(avl=True)
cost=0
for i in range(N):
dp.add_line(-2*X[i],cost+X[i]**2+Y[i]**2)
cost=dp(A[i])+A[i]**2
ans=cost
print(ans)
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0