poj 3667 Hotel

http://poj.org/problem?id=3667

题目大意:给定长度n的空序列和m个操作。操作分两种:

1 x:询问长度为x的最左端的空子序列,输出子序列左端点。

2 x l:清空从x开始长度为l的序列(不一定l长度里面都是非空的)。

 

比较基础的线段树实现的段修改。线段树上每个单元记录当前段中最长的空段max,左端开始最长的空段lmax,右端开始最长的空段rmax。

 

AC CODE

program pku_3667;
var max,lmax,rmax:array[1..200000] of longint;
    p:array[1..200000] of boolean;
    i,n,m,x,s,t,l,command:longint;
//============================================================================
procedure cover(be,en,now:longint);
var mid:longint;
begin
  if (s<=be) and (t>=en) then
  begin
    max[now]:=(en-be+1)*x;
    lmax[now]:=max[now];
    rmax[now]:=max[now];
    p[now]:=true; exit;
  end; mid:=(be+en) shr 1;
  if p[now] then
  begin
    max[now shl 1]:=max[now] div (en-be+1)*(mid-be+1);
    lmax[now shl 1]:=max[now shl 1]; rmax[now shl 1]:=max[now shl 1];
    max[now shl 1+1]:=max[now] div (en-be+1)*(en-mid);
    lmax[now shl 1+1]:=max[now shl 1+1]; rmax[now shl 1+1]:=max[now shl 1+1];
    p[now shl 1]:=true; p[now shl 1+1]:=true; p[now]:=false;
  end;
  if s<=mid then cover(be,mid,now shl 1);
  if t>mid then cover(mid+1,en,now shl 1+1);
  if max[now shl 1]>max[now shl 1+1] then
    max[now]:=max[now shl 1] else max[now]:=max[now shl 1+1];
  if rmax[now shl 1]+lmax[now shl 1+1]>max[now] then
    max[now]:=rmax[now shl 1]+lmax[now shl 1+1];
  if lmax[now shl 1]=mid-be+1 then    //不仅要更行max还有lmax,rmax。
    lmax[now]:=lmax[now shl 1]+lmax[now shl 1+1] else lmax[now]:=lmax[now shl 1];
  if rmax[now shl 1+1]=en-mid then
    rmax[now]:=rmax[now shl 1]+rmax[now shl 1+1] else rmax[now]:=rmax[now shl 1+1];
end;
//============================================================================
function find(be,en,now:longint):longint;
var mid:longint;
begin
  if en-be+1=x then exit(be);
  mid:=(be+en) shr 1;
  if p[now] then    //在询问的时候也要推标号,及时更新。
  begin
    max[now shl 1]:=max[now] div (en-be+1)*(mid-be+1);
    lmax[now shl 1]:=max[now shl 1]; rmax[now shl 1]:=max[now shl 1];
    max[now shl 1+1]:=max[now] div (en-be+1)*(en-mid);
    lmax[now shl 1+1]:=max[now shl 1+1]; rmax[now shl 1+1]:=max[now shl 1+1];
    p[now shl 1]:=true; p[now shl 1+1]:=true; p[now]:=false;
  end;
  if max[now shl 1]>=x then find:=find(be,mid,now shl 1) else
  if rmax[now shl 1]+lmax[now shl 1+1]>=x then find:=mid-rmax[now shl 1]+1 else
  find:=find(mid+1,en,now shl 1+1);
end;
//============================================================================
begin
  readln(n,m);
  max[1]:=n; p[1]:=true;
  lmax[1]:=n; rmax[1]:=n;
  for i:=1 to m do
  begin
    read(command);
    if command=1 then
    begin
      readln(x);
      if max[1]>=x then
      begin
        s:=find(1,n,1); t:=s+x-1; x:=0;
        cover(1,n,1); writeln(s);
      end else writeln('0')
    end else
    begin
      readln(s,l); t:=s+l-1; x:=1;
      cover(1,n,1);
    end;
  end;
end.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值