[BZOJ1593] [Usaco2008 Feb]Hotel 旅馆

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1593

题目大意

两种操作
1.询问连续长度为x的最左端点,并将这段覆盖
2.将区间[L,R]区间取消覆盖

题解

记录区间
1.左端点连续没覆盖的长度
2.右端点连续没覆盖的长度
3.区间最长连续没覆盖的长度
修改之后回溯的时候合并注意讨论即可
详细见code

const
 maxn=50005;
var
 w:array[0..8*maxn,1..7]of longint;
 i,j,k:longint;
 n,m,a,b,c,ans:longint;
procedure build(a,l,r:longint);
var mid:longint;
begin
 w[a,1]:=l; w[a,2]:=r; w[a,3]:=r-l+1; w[a,4]:=r-l+1; w[a,5]:=r-l+1; w[a,6]:=-1;
 if l=r then exit;
 mid:=(l+r)>>1;
 build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;

procedure pushdown(a:longint);
begin
 if (w[a,6]=0)and(w[a,1]<>w[a,2]) then begin
  w[a<<1,3]:=w[a<<1,2]-w[a<<1,1]+1; w[a<<1,4]:=w[a<<1,3]; w[a<<1,5]:=w[a<<1,3];
  w[a<<1+1,3]:=w[a<<1+1,2]-w[a<<1+1,1]+1; w[a<<1+1,4]:=w[a<<1+1,3]; w[a<<1+1,5]:=w[a<<1+1,3];
  w[a<<1,6]:=w[a,6]; w[a<<1+1,6]:=w[a,6];
 end;
 if (w[a,6]=1)and(w[a,1]<>w[a,2]) then begin
  w[a<<1,3]:=0; w[a<<1,4]:=0; w[a<<1,5]:=0;
  w[a<<1+1,3]:=0; w[a<<1+1,4]:=0; w[a<<1+1,5]:=0;
  w[a<<1,6]:=w[a,6]; w[a<<1+1,6]:=w[a,6];
 end;
 w[a,6]:=-1;
end;

function query(a,b:longint):longint;
var mid:longint;
begin
 if w[a,6]<>-1 then pushdown(a);
 if w[a,1]=w[a,2] then exit(1);
 mid:=(w[a,1]+w[a,2])>>1;
 if w[a<<1,5]>=b then exit(query(a<<1,b)) else
 if w[a<<1,4]+w[a<<1+1,3]>=b then exit(mid-w[a<<1,4]+1)
 else exit(query(a<<1+1,b));
end;

procedure update(a,l,r,c:longint);
var mid,d:longint;
begin
 if w[a,6]<>-1 then pushdown(a);
 if (w[a,1]=l)and(w[a,2]=r) then begin
  w[a,6]:=c;
  if c=1 then d:=0 else d:=w[a,2]-w[a,1]+1;
  w[a,3]:=d; w[a,4]:=d; w[a,5]:=d;
  exit;
 end;
 mid:=(w[a,1]+w[a,2])>>1;
 if r<=mid then update(a<<1,l,r,c) else
 if l>mid then update(a<<1+1,l,r,c)
 else begin
  update(a<<1,l,mid,c);
  update(a<<1+1,mid+1,r,c);
 end;
 w[a,3]:=w[a<<1,3]; w[a,4]:=w[a<<1+1,4];
 if w[a<<1,4]=w[a<<1,2]-w[a<<1,1]+1 then inc(w[a,3],w[a<<1+1,3]);
 if w[a<<1+1,3]=w[a<<1+1,2]-w[a<<1+1,1]+1 then inc(w[a,4],w[a<<1,4]);
 w[a,5]:=w[a<<1,5]; if w[a<<1+1,5]>w[a,5] then w[a,5]:=w[a<<1+1,5];
 if w[a<<1,4]+w[a<<1+1,3]>w[a,5] then w[a,5]:=w[a<<1,4]+w[a<<1+1,3];
end;

begin
 readln(n,m);
 build(1,1,n);
 for i:=1 to m do
  begin
   read(a);
   if a=1
   then begin
    readln(b);
    if w[1,5]<b then begin writeln(0); continue; end;
    ans:=query(1,b); writeln(ans);
    update(1,ans,ans+b-1,1);
   end
   else begin
    readln(b,c);
    update(1,b,b+c-1,0);
   end;
  end;
end.

你可能感兴趣的:([BZOJ1593] [Usaco2008 Feb]Hotel 旅馆)