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.