結果

問題 No.703 ゴミ拾い Easy
ユーザー vwxyzvwxyz
提出日時 2024-11-20 17:44:43
言語 PyPy3
(7.3.15)
結果
RE  
実行時間 -
コード長 16,070 bytes
コンパイル時間 307 ms
コンパイル使用メモリ 82,580 KB
実行使用メモリ 178,028 KB
最終ジャッジ日時 2024-11-20 17:44:55
合計ジャッジ時間 12,322 ms
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 47 ms
55,680 KB
testcase_01 AC 47 ms
55,552 KB
testcase_02 AC 48 ms
55,424 KB
testcase_03 AC 47 ms
55,680 KB
testcase_04 AC 47 ms
55,552 KB
testcase_05 AC 47 ms
55,168 KB
testcase_06 AC 48 ms
55,552 KB
testcase_07 AC 48 ms
55,168 KB
testcase_08 AC 47 ms
54,912 KB
testcase_09 AC 48 ms
55,424 KB
testcase_10 AC 47 ms
54,784 KB
testcase_11 AC 49 ms
55,680 KB
testcase_12 AC 47 ms
55,040 KB
testcase_13 AC 48 ms
54,912 KB
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 RE -
testcase_34 AC 346 ms
161,120 KB
testcase_35 AC 316 ms
161,020 KB
testcase_36 AC 318 ms
160,844 KB
testcase_37 AC 309 ms
160,856 KB
testcase_38 AC 340 ms
161,080 KB
testcase_39 AC 311 ms
161,496 KB
testcase_40 AC 315 ms
160,732 KB
testcase_41 AC 354 ms
161,508 KB
testcase_42 AC 317 ms
161,364 KB
testcase_43 AC 316 ms
161,284 KB
testcase_44 AC 47 ms
55,040 KB
testcase_45 AC 49 ms
55,040 KB
testcase_46 AC 249 ms
178,028 KB
testcase_47 AC 350 ms
165,528 KB
testcase_48 RE -
testcase_49 RE -
権限があれば一括ダウンロードができます

ソースコード

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 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 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 self.right[node_left_right]!=None:
            self.size[node]+=self.size[self.right[node_left_right]]
        self.size[node_left]-=1
        if 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 self.left[node_right_left]!=None:
            self.size[node]+=self.size[self.left[node_right_left]]
        self.size[node_right]-=1
        if 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 self.left[v]!=None:
            stack.append((v,1))
            lmax=self.left[v]
            while 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 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 self.right[node]!=None:
                    stack.append((self.right[node],True))
                stack.append((node,False))
                if 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 self.right[node]!=None:
                    stack.append((self.right[node],True))
                stack.append((node,False))
                if 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 self.right[node]!=None:
                    stack.append((self.right[node],True))
                stack.append((node,False))
                if 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)
0