心理学概论
题目大意
给出
N
个三元组{
<1>把
Ai
加入第一组内。
<2>把
Bi
加入第二组内。
<3>把
Ci
加入第三组内。
定义一个组的的代价为加入进该组的元素的最大值,问三组代价之和的最小值。
数据范围
对于100%的数据, 1≤N≤105 , 1≤Ai,Bi,Ci≤108 。
题解
首先先考虑以下二元组{
Ai
,
Bi
}的情况,将二元组按照
Ai
的值从小到大排序,假设选择了第
i
个二元组的
那现在由二元组换成三元组,一样的思想,按照
假如选择了第
i
组的
从大到小枚举
i
,从后往前做,每次都会将新的二元组{
线段树维护三个值:该段区间内 Bi 最小值,该段区间内 max ( Ci , Ci+1 , ... , Cn )的最小值(设前面那个式子的值为 Gi )以及每一种选法的最小代价(即 Bi + Gi+1 的最小值),对于每次加入一个新的二元组{ Bi , Ci },操作有两种,第一个插入一个 Bi ,第二个是将某一段 Gi 全部变为 Ci ,同时我们可以用二分求出需要更新的区间即可。
Code(Pascal)
const
maxn=maxlongint;
var
tr:array[0..4000000,1..5] of int64;
ba:array[0..200000,1..3] of int64;
pa:array[0..200000,1..2] of longint;
d:array[0..150000] of longint;
la:array[0..4000000] of int64;
n,m,j,k,l,i,wz:longint;
o,oo,ans,kk:int64;
function min(a,b:int64):int64;
begin
if a<b then exit(a)
else exit(b);
end;
function max(a,b:int64):int64;
begin
if a>b then exit(a)
else exit(b);
end;
procedure qsort(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=ba[(l+r) div 2,1];
repeat
while ba[i,1]<m do inc(i);
while ba[j,1]>m do dec(j);
if i<=j then
begin
ba[0]:=ba[i];
ba[i]:=ba[j];
ba[j]:=ba[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure qsortll(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=pa[(l+r) div 2,1];
repeat
while pa[i,1]<m do inc(i);
while pa[j,1]>m do dec(j);
if i<=j then
begin
pa[0]:=pa[i];
pa[i]:=pa[j];
pa[j]:=pa[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsortll(l,j);
if i<r then qsortll(i,r);
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);
begin
tr[o*2,2]:=la[o];
tr[o*2+1,2]:=la[o];
tr[o*2,3]:=tr[o*2,1]+la[o];
tr[o*2+1,3]:=tr[o*2+1,1]+la[o];
la[o*2]:=la[o];
la[o*2+1]:=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,2]:=min(tr[ls,2],tr[rs,2]);
tr[o,3]:=min(tr[ls,3],tr[rs,3]);
end;
function xz(o,l,r,kk:longint):longint;
var
mid:longint;
begin
if l=r then exit(l);
mid:=(l+r) div 2;
if la[o]>0 then down(o);
if tr[o*2,2]<kk then exit(xz(o*2,l,mid,kk))
else exit(xz(o*2+1,mid+1,r,kk));
up(o);
end;
function gx(o,l,r,ll,rr,bh:int64):int64;
var
mid,ls,rs:longint;
begin
if (l=ll) and (r=rr) then
begin
la[o]:=bh;
tr[o,2]:=la[o];
tr[o,3]:=tr[o,1]+la[o];
exit;
end;
if la[o]>0 then down(o);
mid:=(l+r) div 2;
ls:=o*2;
rs:=ls+1;
if rr<=mid then gx(ls,l,mid,ll,rr,bh)
else if ll>mid then gx(rs,mid+1,r,ll,rr,bh)
else
begin
gx(ls,l,mid,ll,mid,bh);
gx(rs,mid+1,r,mid+1,rr,bh);
end;
up(o);
end;
procedure ddxg(o,l,r,kk:int64);
var
mid:longint;
begin
if l=r then
begin
tr[o,1]:=d[kk];
tr[o,3]:=d[kk]+tr[o,2];
exit;
end;
mid:=(l+r) div 2;
if la[o]>0 then down(o);
if kk<=mid then ddxg(o*2,l,mid,kk)
else ddxg(o*2+1,mid+1,r,kk);
up(o);
end;
begin
assign(input,'psy.in'); reset(input);
assign(output,'psy.out'); rewrite(output);
readln(n);
for i:=1 to n do
readln(ba[i,1],ba[i,2],ba[i,3]);
qsort(1,n);
ans:=ba[n,1];
for i:=1 to n do
begin
pa[i,1]:=ba[i,2];
pa[i,2]:=i;
end;
qsortll(1,n);
oo:=1;
kk:=0;
for i:=1 to n do
if pa[i,1]<>kk then
begin
inc(oo);
d[oo]:=pa[i,1];
kk:=pa[i,1];
ba[pa[i,2],2]:=oo;
end else ba[pa[i,2],2]:=oo;
jl(1,1,oo);
d[0]:=0;
ddxg(1,1,oo,1);
ba[0,1]:=0;
for i:=n downto 1 do
begin
if ba[i,2]<>1 then
begin
wz:=xz(1,1,oo,ba[i,3]);
if wz<ba[i,2] then
gx(1,1,oo,wz,ba[i,2]-1,ba[i,3]);
end;
ddxg(1,1,oo,ba[i,2]);
ans:=min(ans,ba[i-1,1]+tr[1,3]);
end;
writeln(ans);
end.