bzoj 2151 贪心
几乎完全类似于1150的思路,直接参考那个就行了。
http://www.cnblogs.com/BLADEVIL/p/3527193.html
/************************************************************** Problem: 2151 User: BLADEVIL Language: Pascal Result: Accepted Time:3224 ms Memory:15092 kb ****************************************************************/ //By BLADEVIL type pointer=^rec; rec =record pred, succ :pointer; num, fuck :longint; end; shit =record shit1, shit2 :longint; end; var n, m :longint; a :array[0..200010] of pointer; left, right, size :array[0..400010] of longint; key, adr :array[0..400010] of longint; t, tot :longint; ans :longint; procedure left_rotate(var t:longint); var k :longint; begin k:=right[t]; right[t]:=left[k]; left[k]:=t; size[k]:=size[t]; size[t]:=size[left[t]]+size[right[t]]+1; t:=k; end; procedure right_rotate(var t:longint); var k :longint; begin k:=left[t]; left[t]:=right[k]; right[k]:=t; size[k]:=size[t]; size[t]:=size[left[t]]+size[right[t]]+1; t:=k; end; procedure maintain(var t:longint;flag:boolean); begin if not flag then begin if size[left[left[t]]]>size[right[t]] then right_rotate(t) else if size[right[left[t]]]>size[right[t]] then begin left_rotate(left[t]); right_rotate(t); end else exit; end else begin if size[right[right[t]]]>size[left[t]] then left_rotate(t) else if size[left[right[t]]]>size[left[t]] then begin right_rotate(right[t]); left_rotate(t); end else exit; end; maintain(left[t],false); maintain(right[t],true); maintain(t,true); maintain(t,false); end; procedure insert(var t:longint;v,k:longint); begin if t=0 then begin inc(tot); t:=tot; left[t]:=0; right[t]:=0; size[t]:=1; key[t]:=v; adr[t]:=k; end else begin inc(size[t]); if v<key[t] then insert(left[t],v,k) else if v>key[t] then insert(right[t],v,k) else if v=key[t] then if k>adr[t] then insert(right[t],v,k) else insert(left[t],v,k); maintain(t,v>=key[t]); end; end; function delete(var t:longint;v,k:longint):shit; var damn :shit; begin dec(size[t]); if (v=key[t]) and (k=adr[t]) or (v>key[t]) and (right[t]=0) or (v<key[t]) and (left[t]=0) then begin delete.shit1:=key[t]; delete.shit2:=adr[t]; if (left[t]=0) or (right[t]=0) then t:=left[t]+right[t] else begin damn:=delete(left[t],v+1,k); key[t]:=damn.shit1; adr[t]:=damn.shit2; end; end else if v<key[t] then delete:=delete(left[t],v,k) else if v>key[t] then delete:=delete(right[t],v,k) else if v=key[t] then if k>adr[t] then delete:=delete(right[t],v,k) else if k<adr[t] then delete:=delete(left[t],v,k); end; function mini(var t:longint):longint; begin if right[t]=0 then exit(adr[t]) else exit(mini(right[t])); end; procedure init; var i :longint; null :pointer; begin read(n,m); if m>n>>1 then begin writeln('Error!'); halt; end; for i:=1 to n do begin new(null); a[i]:=null; read(a[i]^.num); end; for i:=1 to n do begin if i=1 then a[i]^.pred:=a[n] else a[i]^.pred:=a[i-1]; if i=n then a[i]^.succ:=a[1] else a[i]^.succ:=a[i+1]; end; for i:=1 to n do a[i]^.fuck:=i; end; procedure main; var i :longint; x :longint; begin t:=0; for i:=1 to n do insert(t,a[i]^.num,i); for i:=1 to m do begin x:=mini(t); ans:=ans+a[x]^.num; delete(t,a[x]^.num,a[x]^.fuck); delete(t,a[x]^.pred^.num,a[x]^.pred^.fuck); delete(t,a[x]^.succ^.num,a[x]^.succ^.fuck); a[x]^.num:=a[x]^.pred^.num+a[x]^.succ^.num-a[x]^.num; insert(t,a[x]^.num,x); a[x]^.pred^.pred^.succ:=a[x]; a[x]^.pred:=a[x]^.pred^.pred; a[x]^.succ^.succ^.pred:=a[x]; a[x]^.succ:=a[x]^.succ^.succ; end; writeln(ans); end; begin init; main; end.