## bzoj 2151 贪心

几乎完全类似于1150的思路，直接参考那个就行了。

/**************************************************************
Problem: 2151
Language: Pascal
Result: Accepted
Time:3224 ms
Memory:15092 kb
****************************************************************/

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;
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;
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
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];
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;
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
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
if m>n>>1 then
begin
writeln('Error!');
halt;
end;
for i:=1 to n do
begin
new(null);
a[i]:=null;
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.

posted on 2014-01-20 17:24  BLADEVIL  阅读(241)  评论(0编辑  收藏  举报