现在的位置: 首页 > 综合 > 正文

poj3667

2018年04月26日 ⁄ 综合 ⁄ 共 2150字 ⁄ 字号 评论关闭

【题意】

一共有n个空位,初始全为空,会有两种操作,一种是询问是否有r个连续的空位,若有,则将最左端有r个连续的空位的地方全部填满,若没有则不填,另一种是将从u开始的d个位置全部清空

【输入】

第一行两个数n、m(<=50000),表示n个空位,m次操作

接下来m行每行表示一次操作,

若该行第一个数字为1,接下来是一个数字,表示操作一

若该行第一个数字为2,接下来是两个数字,表示操作二

【输出】

对于每个操作一,若存在r个连续的空位,则输出最靠左的r个连续空位的起点,若不存在则输出0

线段树

每个节点记录三个值,从该节点左端往右有多少个连续的空位,从该节点右端往左有多少个连续的空位,该区间内最长连续空位长度为多少

program poj3667;
var
  tot,n,m,i,j,k,r,o,s,e:longint;
  left,right,x,y,point:array [0..200001] of longint;

function max (a,b:longint):longint;
begin
  if a>b then exit(a)
         else exit(b);
end;

procedure down (now,l,r:longint);
begin
  if left[now]=0 then
    begin
      inc(tot);
      left[now]:=tot;
    end;
  if right[now]=0 then
    begin
      inc(tot);
      right[now]:=tot;
    end;
  if point[now]=r-l+1 then
    begin
      x[left[now]]:=(l+r) div 2 - l + 1;
      y[left[now]]:=(l+r) div 2 - l + 1;
      point[left[now]]:=(l+r) div 2 - l + 1;
      x[right[now]]:=r-(l+r) div 2;
      y[right[now]]:=r-(l+r) div 2;
      point[right[now]]:=r-(l+r) div 2;
    end;
  if point[now]=0 then
    begin
      x[left[now]]:=0;
      y[left[now]]:=0;
      point[left[now]]:=0;
      x[right[now]]:=0;
      y[right[now]]:=0;
      point[right[now]]:=0;
    end;
end;

procedure fill (s,e,p,l,r,now:longint);
var
  mid:longint;
begin
  if (s=l)and(e=r) then
    begin
      if p=0 then
        begin
          x[now]:=r-l+1;
          y[now]:=r-l+1;
          point[now]:=r-l+1;
        end
             else
        begin
          x[now]:=0;
          y[now]:=0;
          point[now]:=0;
        end;
      exit;
    end;
  mid:=(l+r) div 2;
  down(now,l,r);
  if e<=mid then fill(s,e,p,l,mid,left[now])
            else
  if s>=mid+1 then fill(s,e,p,mid+1,r,right[now])
              else
    begin
      fill(s,mid,p,l,mid,left[now]);
      fill(mid+1,e,p,mid+1,r,right[now]);
    end;
  if x[left[now]]=mid-l+1 then x[now]:=x[left[now]]+x[right[now]]
                          else x[now]:=x[left[now]];
  if y[right[now]]=r-mid then y[now]:=y[right[now]]+y[left[now]]
                         else y[now]:=y[right[now]];
  point[now]:=max(y[left[now]]+x[right[now]],max(point[left[now]],point[right[now]]));
end;

function find (p,l,r,now:longint):longint;
begin
  if (p=point[now])and(r-l+1=point[now]) then exit(l);
  down(now,l,r);
  if point[left[now]]>=p then exit(find(p,l,(l+r) div 2,left[now]))
                         else
  if (y[left[now]]<>0)and(y[left[now]]+x[right[now]]>=p) then exit((l+r) div 2 + 1 - y[left[now]])
                                                         else exit(find(p,(l+r) div 2 + 1,r,right[now]));
end;

begin
  read(n,m);
  tot:=0;
  x[0]:=n;
  y[0]:=n;
  point[0]:=n;
  for i:=1 to m do
    begin
      read(o);
      if o=1 then
        begin
          read(r);
          if point[0]<r then
            writeln(0)

                        else
            begin
              k:=find(r,1,n,0);
              writeln(k);
              fill(k,k+r-1,1,1,n,0);
            end;
        end
             else
        begin
          read(s,e);
          e:=s+e-1;
          fill(s,e,0,1,n,0);
        end;
    end;
end.
【上篇】
【下篇】

抱歉!评论已关闭.