【题意】
一共有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.