您的位置:首页 > 其它

poj1823,3667

2013-12-14 20:05 295 查看
又来练线段树了……

poj1823题意很简单(明显的数据结构题),区间修改和统计最长连续空区间;

有了poj3468的基础,区间修改不是什么问题了,重点是求最长连续空区间;(弱弱的我纠结了好久)

在每个节点上增加3个域,lmax,rmax,maxx,分别表示从左起最长,右起最长,区间内最长,然后稍稍动点脑筋即可……

附代码:

type node=record

lmax,rmax,maxx:longint;

l,r,lazy:integer; //lazy表示区间三种情况,-1表示区间内有人住但未满,0表示无人住,1表示全住满

end;

var tree:array[0..80000] of node;

i,n,m,a,b,c,j:longint;

procedure updata(i:longint); //更新

var p:longint;

begin

if tree[i].lazy<>-1 then

begin

if tree[i].lazy=0 then p:=tree[i].r-tree[i].l+1 else p:=0;

tree[i].lmax:=p;

tree[i].rmax:=p;

tree[i].maxx:=p;

end

else begin //看起来很繁琐,实际上仔细想想就明白了

tree[i].lmax:=tree[i*2].lmax;

if tree[i].lmax=tree[i*2].r-tree[i*2].l+1 then tree[i].lmax:=tree[i].lmax+tree[i*2+1].lmax;

tree[i].rmax:=tree[i*2+1].rmax;

if tree[i].rmax=tree[i*2+1].r-tree[i*2+1].l+1 then tree[i].rmax:=tree[i].rmax+tree[i*2].rmax;

p:=max(tree[i].lmax,tree[i].rmax);

p:=max(p,max(tree[i*2].maxx,tree[i*2+1].maxx));

tree[i].maxx:=max(p,tree[i*2].rmax+tree[i*2+1].lmax);

end;

end;

procedure pushdown(i:longint); //lazy思想,注意标记下移的时候不忘更新,因为某个子区间不一定会被访问

begin

tree[i*2].lazy:=tree[i].lazy;

updata(i*2);

tree[i*2+1].lazy:=tree[i].lazy;

updata(i*2+1);

tree[i].lazy:=-1; //需要标记下移的时候当前区间一定不会是全满或全空(想想为什么)

end;

procedure build(i,l,r:longint); //初始化线段树

var m:longint;

begin

tree[i].l:=l; tree[i].r:=r;

tree[i].lazy:=0;

updata(i);

if l<>r then

begin

m:=(l+r) div 2;

build(i*2,l,m);

build(i*2+1,m+1,r);

end;

end;

procedure work(i,l,r,t:longint);

var m:longint;

begin

if (l>=a) and (r<=b) then

begin

tree[i].lazy:=t;

updata(i);

end

else if l<>r then begin

if tree[i].lazy<>-1 then pushdown(i);

m:=(l+r) div 2;

if (a<=m) then work(i*2,l,m,t);

if (b>=m+1) then work(i*2+1,m+1,r,t);

updata(i); // 左右子区间访问过后更新当前区间

end;

end;

begin

readln(n,m);

build(1,1,n);

for i:=1 to m do

begin

read(c);

if c<>3 then

begin

readln(a,b);

b:=a+b-1;

if c=1 then work(1,1,n,1) else work(1,1,n,0); //1代表入住,0代表退房

end

else if c=3 then writeln(tree[1].maxx);

end;

end.

话说线段树查起来真累(难道还是我太渣了?),耗了5次才AC

poj3667在poj1823基础上多了个查找但并不难,对于当前区间,按照从左区间到右区间的优先顺序找即可,一次AC
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: