JZOJ 4867 【NOIP2016提高A组集训第8场11.5】心理学概论

来源:互联网 发布:jdk 1.8 linux tar gz 编辑:程序博客网 时间:2024/05/11 12:04

心理学概论

题目大意

给出N个三元组{Ai,Bi,Ci},对于每一个三元组,有三个以下的操作:
<1>把Ai加入第一组内。
<2>把Bi加入第二组内。
<3>把Ci加入第三组内。
定义一个组的的代价为加入进该组的元素的最大值,问三组代价之和的最小值。

数据范围

对于100%的数据,1N1051Ai,Bi,Ci108

题解

首先先考虑以下二元组{Ai,Bi}的情况,将二元组按照Ai的值从小到大排序,假设选择了第i个二元组的Ai作为第1组的代价,那么第1~i-1个二元组当然也可以选入第一组,剩下的只能选入第二组,此时的总代价为Ai+max(Bi+1,Bi+2,...,Bn),枚举iO(n)统计答案即可。

那现在由二元组换成三元组,一样的思想,按照Ai的值从小到大对三元组排序。
假如选择了第i组的Ai作为第一组的代价,那么第1~i-1个三元组也可以选入第一组,剩下的第i+1~n组只能选入第二组和第三组,第i+1~n组的BiCi分开求其最小代价即可。

从大到小枚举i,从后往前做,每次都会将新的二元组{Bi,Ci}加入维护只选BiCi的最小值。关于从第i+1~n个三元组中只选BiCi时的最小代价,也就是关于二元组的求值,我们可以用一开始的方法,但因为我们要做N次,所以我们要用到线段树降低时间复杂度,同时我们可以避免排序。

线段树维护三个值:该段区间内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.
0 0
原创粉丝点击