搞了一个下午,终于搞定了,这题是线段树的区间合并!
以前有做过类似的题目,所以还是有点感觉的!
在统计区间的时候,看了一下别人的统计方法!
终于写出来的!呵呵!!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max 50005
struct node
{
int l,r;
int rsum,lsum;//从最左端连续的区间数,从右端到末端的区间数
int sum;//这个区间的空房间总数
int flag;//-1代表区间的有空的,也有不空,1代表房间已满,0代表这段区间的房间是空的
}tree[4*Max];
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int ans,a,b;
void build(int step,int l,int r)
{
tree[step].l=l;
tree[step].r=r;
tree[step].flag=0;
tree[step].sum=tree[step].lsum=tree[step].rsum=r-l+1;
if(l==r)
return ;
int mid=(l+r)>>1;
build(step<<1,l,mid);
build(step<<1|1,mid+1,r);
}
void updata(int step,int l,int r,int x)
{
if(tree[step].l==l&&tree[step].r==r)
{
tree[step].flag=x;
if(x==1)
{
tree[step].sum=tree[step].lsum=tree[step].rsum=0;
}
else
{
tree[step].sum=tree[step].lsum=tree[step].rsum=tree[step].r-tree[step].l+1;
}
return ;
}
if(tree[step].flag!=-1)//传递父亲的性质
{
tree[step<<1].flag=tree[step<<1|1].flag=tree[step].flag;
if(tree[step].flag==0)
{
tree[step<<1].sum=tree[step<<1].lsum=tree[step<<1].rsum=tree[step<<1].r-tree[step<<1].l+1;
tree[step<<1|1].sum=tree[step<<1|1].lsum=tree[step<<1|1].rsum=tree[step<<1|1].r-tree[step<<1|1].l+1;
}
else
{
tree[step<<1].sum=tree[step<<1].lsum=tree[step<<1].rsum=0;
tree[step<<1|1].sum=tree[step<<1|1].lsum=tree[step<<1|1].rsum=0;
}
tree[step].flag=-1;
}
int mid=(tree[step].l+tree[step].r)>>1;
if(r<=mid)
{
updata(step<<1,l,r,x);
}
else
{
if(l>mid)
{
updata(step<<1|1,l,r,x);
}
else
{
updata(step<<1,l,mid,x);
updata(step<<1|1,mid+1,r,x);
}
}
//合并区间,把孩子的性质合并给父亲
tree[step].lsum=tree[step<<1].lsum;
tree[step].rsum=tree[step<<1|1].rsum;
tree[step].sum=max(max(tree[step<<1].sum,tree[step<<1|1].sum),tree[step<<1].rsum+tree[step<<1|1].lsum);//取左孩子的区间数,右孩子区间数,左右区间合并起来的区间数的最大值
if(tree[step].lsum==(tree[step<<1].r-tree[step].l+1))//合并后,如果左孩子整个区间跨约右孩子
tree[step].lsum+=tree[step<<1|1].lsum;
if(tree[step].rsum==(tree[step<<1|1].r-tree[step<<1|1].l+1))//部分的左孩子跨越整个右孩子
tree[step].rsum+=tree[step<<1].rsum;
}
int compute(int step)
{
int m=(tree[step].r+tree[step].l)>>1;
if(tree[step].flag==0&&tree[step].sum>=a)
return tree[step].l;
if(tree[step].flag==-1)//含有多个区间段,有空,有不空
{
if(tree[step<<1].sum>=a)//优先考虑左孩子
{
return compute(step<<1);
}
else
if((tree[step<<1].rsum+tree[step<<1|1].lsum)>=a)//中间的区域
return m-tree[step<<1].rsum+1;
else
return compute(step<<1|1);//右孩子
}
return -1;
}
int main()
{
int n,m,op;
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&a);
if(tree[1].sum<a)
{
printf("0\n");
continue;
}
ans=compute(1);
printf("%d\n",ans);
updata(1,ans,ans+a-1,1);
}
else
{
scanf("%d%d",&a,&b);
updata(1,a,a+b-1,0);
}
}
return 0;
}