线段树之二

//poj 3667 Hotel

#include
<iostream> //线段树,求连续区间的长度
using namespace std;
struct node
{
int l,r,blank;
int lb,rb; //lb(rb)记录从左(右)端点开始的连续空的线段长
}tree[2000000];
void build_tree(int n,int s,int t)
{
tree[n].l
=s;tree[n].r=t;
tree[n].blank
=tree[n].lb=tree[n].rb=t-s+1;
if(s<t)
{
int mid=(s+t)>>1;
build_tree(
2*n,s,mid);
build_tree(
2*n+1,mid+1,t);
}
}
void upd_blank(int n) //在modify_in,modify_out,query函数内都要用到upd_blank,update来更新区间情况,所以封装起来
{
if(tree[n].blank==0)
{
tree[
2*n].blank=tree[2*n+1].blank=0;
tree[
2*n].lb=tree[2*n].rb=tree[2*n+1].lb=tree[2*n+1].rb=0;
}
if(tree[n].blank==tree[n].r-tree[n].l+1)
{
tree[
2*n].blank=tree[2*n].r-tree[2*n].l+1;
tree[
2*n+1].blank=tree[2*n+1].r-tree[2*n+1].l+1;
tree[
2*n].lb=tree[2*n].rb=tree[2*n].r-tree[2*n].l+1;
tree[
2*n+1].lb=tree[2*n+1].rb=tree[2*n+1].r-tree[2*n+1].l+1;
}
}
void update(int n)
{
tree[n].blank
=tree[2*n].blank+tree[2*n+1].blank;
tree[n].lb
=tree[2*n].lb;
if(tree[2*n].lb==tree[2*n].r-tree[2*n].l+1)
tree[n].lb
+=tree[2*n+1].lb;
tree[n].rb
=tree[2*n+1].rb;
if(tree[2*n+1].rb==tree[2*n+1].r-tree[2*n+1].l+1)
tree[n].rb
+=tree[2*n].rb;
}
void modify_in(int n,int s,int t)
{
upd_blank(n);
if(tree[n].l==s&&tree[n].r==t) //这道题同样地不能一直更新到叶子节点,即tree[n].l==tree[n].r,否则TLE
{
tree[n].blank
=0;
tree[n].lb
=tree[n].rb=0;
}
else
{
int mid=(tree[n].l+tree[n].r)>>1;
if(s<=mid)
modify_in(
2*n,s,min(mid,t));
if(t>mid)
modify_in(
2*n+1,max(s,mid+1),t);
update(n);
}
}
void modify_out(int n,int s,int t)
{
upd_blank(n);
if(tree[n].l==s&&tree[n].r==t)
{
tree[n].blank
=tree[n].lb=tree[n].rb=tree[n].r-tree[n].l+1;
}
else
{
int mid=(tree[n].l+tree[n].r)>>1;
if(s<=mid)
modify_out(
2*n,s,min(mid,t));
if(t>mid)
modify_out(
2*n+1,max(s,mid+1),t);
update(n);
}
}
bool query(int n,int len)
{
upd_blank(n);
if(tree[n].r-tree[n].l+1<len||tree[n].blank<len)
return false;
if(tree[n].blank==tree[n].r-tree[n].l+1)
{
modify_in(n,tree[n].l,tree[n].l
+len-1); //假如是整个区间都为空的话自然地从左端开始
update(n);
printf(
"%d\n",tree[n].l);
return true;
}
//查询最左连续区间时,注意顺序,首先是左子树,然后是跨越左子树和右子树,即原来区间的中间部分,
//然后是右子树,最后如果都不满足的话则输出0
if(tree[n].lb>=len)
{
modify_in(n,tree[n].l,tree[n].l
+len-1);
update(n);
printf(
"%d\n",tree[n].l);
return true;
}
if(query(2*n,len))
{
update(n);
return true;
}
if(tree[2*n].rb+tree[2*n+1].lb>=len)
{
int a=tree[2*n].rb;
//要特别注意这里必须用另一变量存储tree[2*n].rb,因为执行后面第一句modify_in()后,
//tree[2*n].rb的值将会发生改变,影响到接下来的正确执行
modify_in(2*n,tree[2*n].r-a+1,tree[2*n].r);
modify_in(
2*n+1,tree[2*n+1].l,tree[2*n+1].l+len-a-1);
update(n);
printf(
"%d\n",tree[2*n].r-a+1);
return true;
}
if(query(2*n+1,len))
{
update(n);
return true;
}
return false;
}
int main()
{
int n,m,tag,x,d;
scanf(
"%d%d",&n,&m);
build_tree(
1,1,n);
while(m--)
{
scanf(
"%d",&tag);
if(tag==1)
{
scanf(
"%d",&d);
bool flag=query(1,d);
if(!flag)
printf(
"0\n");
}
else
{
scanf(
"%d%d",&x,&d);
modify_out(
1,x,x+d-1);
}
}
return 0;
}

  

posted on 2011-07-17 01:56  sysu_mjc  阅读(147)  评论(0编辑  收藏  举报

导航