poj 1823 hotel(线段树)

题目

线段树的区间更新

Problem: 1823       
Memory: 1644K       
Time: 2938MS

program hotel;
const maxN=16000*4;
type rec = record
      left,right,value,lm,rm,mark:longint; end;     //lm表示从左开始最多连续多少个,lr同理
var                                                     
  n,k,i,a,mem,l:longint;
  tree:array[1..maxN]of rec;

function max(a,b:longint):longint;
begin
    if a>b then max:=a
    else max:=b;
end;

procedure buildtree(l,r,k:longint);
var mid:longint;
begin
 tree[k].left:=l;
 tree[k].right:=r;
 tree[k].value:=r-l+1;
 tree[k].lm:=r-l+1;
 tree[k].rm:=r-l+1;
 tree[k].mark:=-1; 
 if l=r then exit;
 mid:=(l+r)div 2;
 buildtree(l,mid,k*2);
 if mid<r then
  buildtree(mid+1,r,k*2+1);
end;

procedure pushdown(k:longint);
var t:longint;
begin
 if tree[k].mark=-1 then exit; //-1表示已经更新完毕
 if tree[k].mark=0 then begin
  t:=tree[k*2].right-tree[k*2].left+1;
  tree[k*2].value:=t;
  tree[k*2].lm:=t;
  tree[k*2].rm:=t;
  tree[k*2].mark:=0;
  t:=tree[k*2+1].right-tree[k*2+1].left+1;
  tree[k*2+1].value:=t;
  tree[k*2+1].lm:=t;
  tree[k*2+1].rm:=t;
  tree[k*2+1].mark:=0;
 end
 else begin
  tree[k*2].value:=0;
  tree[k*2].lm:=0;
  tree[k*2].rm:=0;
  tree[k*2].mark:=1;
  tree[k*2+1].value:=0;
  tree[k*2+1].lm:=0;
  tree[k*2+1].rm:=0;
  tree[k*2+1].mark:=1;
 end;
 tree[k].mark:=-1;
end;

procedure pushup(k:longint);
var a,b,c:longint;
begin
 a:=tree[k*2].value;
 b:=tree[k*2+1].value;
 c:=tree[k*2].rm+tree[k*2+1].lm;
 tree[k].value:=max(max(a,b),c);
 tree[k].lm:=tree[k*2].lm;
 tree[k].rm:=tree[k*2+1].rm;
 if (tree[k*2].lm=(tree[k*2].right-tree[k*2].left+1)) then tree[k].lm:=tree[k].lm+tree[k*2+1].lm;
 if (tree[k*2+1].rm=(tree[k*2+1].right-tree[k*2+1].left+1)) then tree[k].rm:=tree[k].rm+tree[k*2].rm;
end;

procedure update(l,r,w,k:longint);
begin
 if (tree[k].left=l)and(tree[k].right=r) then begin
   if w=1 then begin
    tree[k].value:=0;
    tree[k].mark:=1;
    tree[k].lm:=0;
    tree[k].rm:=0;
   end
   else if w=0 then begin
    tree[k].value:=r-l+1;
    tree[k].mark:=0;
    tree[k].lm:=r-l+1;
    tree[k].rm:=r-l+1;
   end;
  exit;
 end;
 pushdown(k);//更新子树
 if tree[k*2].right>=r then
   update(l,r,w,k*2)
 else if tree[k*2+1].left<=l then update(l,r,w,k*2+1)
 else begin
  update(l,tree[k*2].right,w,k*2);
  update(tree[k*2+1].left,r,w,k*2+1);
 end;
 pushup(k);//更新父节点值域
end;

begin
 readln(n,k);
 buildtree(1,n,1);
 for i:=1 to k do begin
  read(a);
  if a=3 then writeln(tree[1].value)
  else begin
   readln(l,mem);
   if a=1 then update(l,l+mem-1,1,1)
   else update(l,l+mem-1,0,1);
  end;
 end;
end.

反思:
1.发现自己的分析能力还有很大上升空间…看其他人写题解什么的能把问题分析得清清楚楚的,我完全不知道怎么写题解…还是练习少了吧…
2.觉得代码还有可以简化的地方,继续加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值