bzoj1293: [SCOI2009]生日礼物

来源:互联网 发布:国家数据恢复中心费用 编辑:程序博客网 时间:2024/03/29 15:24

传送门
枚举起点找出每一种颜色在这个位置之后的第一个位置与这个位置距离的最大值,再找出每一个起点结果的最小值
转移时将当前节点坐标转移到下一个有这个颜色的位置。
可以用堆或者这个是叫做单调队列么?

uses math;var  a:array [0..1000006] of longint;  p,h,l:array [0..65] of longint;  n,m,i,j,k,ma,mi,ans:longint;procedure kp(l,r:longint);  var i,j,m,t:longint;  begin    i:=l; j:=r; m:=a[(l+r) div 2];    while (i<=j) do begin      while (a[i]<m) and (i<=r) do inc(i);      while (a[j]>m) and (j>=l) do dec(j);      if (i<=j) then begin        t:=a[i]; a[i]:=a[j]; a[j]:=t;        inc(i); dec(j);    end; end;    if (l<j) then kp(l,j);    if (i<r) then kp(i,r);  end;begin  read(n,m);  for i:=1 to m do begin    read(l[i]); h[i]:=h[i-1]+l[i-1];    for j:=h[i] to h[i]+l[i]-1 do read(a[j]);  end;  p:=h; p[m+1]:=n+1;  ma:=0; mi:=maxlongint;  for i:=1 to m do begin    if (a[h[i]]>ma) then ma:=a[h[i]];    if (a[h[i]]<mi) then mi:=a[h[i]];  end;  ans:=ma-mi;  for i:=1 to n-m do    begin      k:=0;      for j:=1 to m do        if (h[j]+1<>p[j+1]) then          if (k=0) or (a[h[j]]<a[h[k]]) or ((a[h[j]]=a[h[k]]) and (a[h[j]+1]<a[h[k]+1])) then k:=j;      inc(h[k]);      ma:=0; mi:=maxlongint;      for j:=1 to m do begin        if (a[h[j]]>ma) then ma:=a[h[j]];        if (a[h[j]]<mi) then mi:=a[h[j]];      end;      ans:=min(ans,ma-mi);    end;  write(ans);end.
1 0