灵知的太阳信仰
题目大意
给出长度为
N
的序列
数据范围
N≤105 , 1≤Pi≤n , 1≤Ki≤2∗104
题解
设
Fi
表示以
i
为当前最后一段的最后一个时割分代价之和的最小值,转移很显然,这儿就不写了。
求出对于每一个
由
Fj
转移到
Fi−1
的代价为
max
(
Kj+1
,
...
,
Ki−1
),变成转移到
Fi
后,代价为
max
(
Kj+1
,
...
,
Ki
),只多了一个
Ki
,那显然我们可以用一棵线段树来维护三个值:该段区间内
Fi
最小值,该段区间内转移代价最小值,
Fi
+转移代价的最小值。每次转移
log
N
的时间复杂度,维护也是
Code(Pascal)
const
maxn=maxlongint;
var
n,m,j,k,l,i,o,left,wz:longint;
mz,mi:array[0..120000] of longint;
tr:array[0..1050000,1..3] of int64;
last,dq,la,f:array[0..1020000] of int64;
function max(a,b:int64):int64;
begin
if a>b then exit(a) else exit(b);
end;
function min(a,b:int64):int64;
begin
if a<b then exit(a) else exit(b);
end;
procedure jl(o,l,r:longint);
var
mid:longint;
begin
tr[o,1]:=maxn;
tr[o,2]:=0;
tr[o,3]:=maxn;
if l=r then exit;
mid:=(l+r) div 2;
jl(o*2,l,mid);
jl(o*2+1,mid+1,r);
end;
procedure down(o:longint);
var
ls,rs:longint;
begin
ls:=2*o;
rs:=ls+1;
tr[ls,2]:=la[o];
tr[rs,2]:=la[o];
tr[ls,3]:=tr[ls,1]+la[o];
tr[rs,3]:=tr[rs,1]+la[o];
la[ls]:=la[o];
la[rs]:=la[o];
la[o]:=0;
end;
procedure up(o:longint);
var
ls,rs:longint;
begin
ls:=o*2;
rs:=ls+1;
tr[o,1]:=min(tr[ls,1],tr[rs,1]);
tr[o,3]:=min(tr[ls,3],tr[rs,3]);
tr[o,2]:=min(tr[ls,2],tr[rs,2]);
end;
procedure gx(o,l,r,ll,rr,kk:int64);
var
mid,ls,rs:longint;
begin
if (l=ll) and (r=rr) then
begin
la[o]:=kk;
tr[o,2]:=kk;
tr[o,3]:=tr[o,1]+tr[o,2];
exit;
end;
mid:=(l+r) div 2;
ls:=o*2; rs:=ls+1;
if la[o]>0 then down(o);
if ll>mid then gx(rs,mid+1,r,ll,rr,kk)
else if rr<=mid then gx(ls,l,mid,ll,rr,kk)
else
begin gx(ls,l,mid,ll,mid,kk); gx(rs,mid+1,r,mid+1,rr,kk); end;
up(o);
end;
function xz(o,l,r,kk:Longint):longint;
begin
if l=r then exit(l);
if la[o]>0 then down(o);
if tr[o*2,2]<kk then xz:=xz(o*2,l,(l+r) div 2,kk)
else xz:=xz(o*2+1,(l+r) div 2+1,r,kk);
up(o);
end;
procedure ddxg(o,l,r,k:longint);
var mid:longint;
begin
mid:=(l+r) div 2;
if l=r then
begin
tr[o,1]:=f[k];
tr[o,3]:=f[k];
exit;
end;
if la[o]>0 then down(o)
else if k<=mid then ddxg(o*2,l,mid,k)
else ddxg(o*2+1,mid+1,r,k);
up(o);
end;
function qz(o,l,r,ll,rr:longint):int64;
var
mid:longint;
begin
if (l=ll) and (r=rr) then exit(tr[o,3]);
mid:=(l+r) div 2;
if la[o]>0 then down(o);
if ll>mid then qz:=qz(o*2+1,mid+1,r,ll,rr)
else if rr<=mid then qz:=qz(o*2,l,mid,ll,rr)
else qz:=min(qz(o*2,l,mid,ll,mid),qz(o*2+1,mid+1,r,mid+1,rr));
up(o);
end;
begin
readln(n);
inc(n);
mz[i]:=-1;
for i:=2 to n do
begin
readln(mz[i],mi[i]);
last[i]:=dq[mz[i]];
dq[mz[i]]:=i;
end;
jl(1,1,n);
left:=1;
f[1]:=mi[1];
ddxg(1,1,n,1);
for i:=2 to n do
begin
left:=max(left,last[i]);
wz:=xz(1,1,n,mi[i]);
if wz<i then
gx(1,1,n,wz,i-1,mi[i]);
f[i]:=qz(1,1,n,left,i-1);
ddxg(1,1,n,i);
end;
writeln(f[n]);
end.