JZOJ 4883 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
2016-11-14 20:58
411 查看
灵知的太阳信仰
题目大意
给出长度为N的序列P和K,现在要将序列分成若干段,必须满足每一段不存在一对(i,j),使得Pi=Pj(即每一段不存在两个相同的Pi),那么这段序列的割分代价就为这段序列中最大的Ki值。现在要将序列分成若干段,求最小的割分代价之和。数据范围
N≤105,1≤Pi≤n,1≤Ki≤2∗104题解
设Fi表示以i为当前最后一段的最后一个时割分代价之和的最小值,转移很显然,这儿就不写了。求出对于每一个Pi上一次Pj=Pi的j的位置,这样就可以知道每一次最前可以由前面的哪个Fj转移过来。
由Fj转移到Fi−1的代价为max(Kj+1 ,..., Ki−1),变成转移到Fi后,代价为max(Kj+1 ,..., Ki),只多了一个Ki,那显然我们可以用一棵线段树来维护三个值:该段区间内Fi最小值,该段区间内转移代价最小值,Fi+转移代价的最小值。每次转移log N的时间复杂度,维护也是log N的时间复杂度,这样就可以将时间复杂度降到O(N 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 ); end.
相关文章推荐
- 【JZOJ4883】【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- [jzoj]4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰(线段树优化DP)
- jzoj 4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- JZOJ4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰 2017.10(B组)
- JZOJ4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- 【JZOJ4882】【NOIP2016提高A组集训第12场11.10】多段线性函数
- JZOJ 4882 【NOIP2016提高A组集训第12场11.10】多段线性函数
- {题解}[jzoj4882]【NOIP2016提高A组集训第12场11.10】多段线性函数
- JZOJ4882. 【NOIP2016提高A组集训第12场11.10】多段线性函数
- JZOJ4884. 【NOIP2016提高A组集训第12场11.10】图的半径
- NOIP2016提高A组集训第12场11.10 总结
- 【NOIP2016提高A组集训第12场11.10】图的半径
- 【NOIP2016提高A组集训第12场11.10】图的半径 解方程找最优解 枚举关键点
- 【JZOJ4884】【NOIP2016提高A组集训第12场11.10】图的半径
- 【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏
- JZOJ 4866. 【NOIP2016提高A组集训第8场11.5】禅与园林艺术
- 【JZOJ4886】【NOIP2016提高A组集训第13场11.11】字符串
- JZOJ4876. 【NOIP2016提高A组集训第10场11.8】基因突变(2017.8B组)