区间合并
说一道例题:poj3667
题意: 两种操作:
1 s 查询有没有连续为s的区间有的话输出最左端的那个位置并把那个区间里的值都减了
2 a s 左端为a长度为s的房间退房 也就是a~a+s-1这个区间值都加一
考虑怎么做。。
可以给线段树里放一个lnum,rnum,num分别代表左边连续最大,右边连续最大,总的连续最大,的空房,然后up的时候当前的lnum就等于左边的lnum;当前的rnum就等于右儿子的rnum;num就等于目前的和 左儿子的 和 右儿子的 和 左儿子的右加右儿子 的左最大值;这里注意计算lnum和rnum的时候 如果左儿子里的区间是满的然后 lnum就不是左儿子的lnum了,还得加一个右儿子的lnum。然后rnum同理,这里一定不能忘了!
代码
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 50006;
struct Node
{
int l,r,lnum,rnum,num,tag;
}node[maxn<<2];
void build(int l,int r,int no)
{
node[no].l=l;
node[no].r=r;
node[no].num=node[no].lnum=node[no].rnum=r-l+1;
node[no].tag=0;
if(l==r)
return;
int mid=l+r>>1;
build(l,mid,no<<1);
build(mid+1,r,no<<1|1);
}
void down(int no)
{
if(node[no].tag==-1)
{
node[no<<1].num=node[no<<1].lnum=node[no<<1].rnum=0;
node[no<<1|1].num=node[no<<1|1].lnum=node[no<<1|1].rnum=0;
}
else
{
node[no<<1].num=node[no<<1].lnum=node[no<<1].rnum=node[no<<1].r-node[no<<1].l+1;
node[no<<1|1].num=node[no<<1|1].lnum=node[no<<1|1].rnum=node[no<<1|1].r-node[no<<1|1].l+1;
}
node[no<<1].tag=node[no<<1|1].tag=node[no].tag;
node[no].tag=0;
}
void up(int no)
{
node[no].lnum=node[no<<1].lnum;
node[no].rnum=node[no<<1|1].rnum;
if(node[no<<1].lnum==node[no<<1].r-node[no<<1].l+1)
{
node[no].lnum+=node[no<<1|1].lnum;
}
if(node[no<<1|1].rnum==node[no<<1|1].r-node[no<<1|1].l+1)
{
node[no].rnum+=node[no<<1].rnum;
}
node[no].num=max(node[no<<1].num,node[no<<1|1].num);
node[no].num=max(node[no<<1].rnum+node[no<<1|1].lnum,node[no].num);
node[no].num=max(node[no].lnum,node[no].num);
node[no].num=max(node[no].rnum,node[no].num);
}
void update(int l,int r,int pos,int no)
{
if(node[no].l>r||node[no].r<l)
return;
if(node[no].l>=l&&node[no].r<=r)
{
if(pos==-1)
node[no].num=node[no].lnum=node[no].rnum=0;
else
{
node[no].num=node[no].lnum=node[no].rnum=node[no].r-node[no].l+1;
}
node[no].tag=pos;
return;
}
if(node[no].tag!=0)
down(no);
update(l,r,pos,no<<1);
update(l,r,pos,no<<1|1);
up(no);
}
int query(int sum,int no)
{
if(node[no].l==node[no].r)
return node[no].l;
if(node[no].tag!=0)
down(no);
if(node[no<<1].num>=sum)
return query(sum,no<<1);
if(node[no<<1].rnum+node[no<<1|1].lnum>=sum)
return node[no<<1].r-node[no<<1].rnum+1;
return query(sum,no<<1|1);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
int f;
scanf("%d",&f);
if(f==1)
{
int x;
scanf("%d",&x);
if(node[1].num>=x)
{
int s=query(x,1);
update(s,s+x-1,-1,1);
printf("%d\n",s);
}
else
printf("0\n");
}
else
{
int x,y;
scanf("%d%d",&x,&y);
update(x,x+y-1,1,1);
}
}
}
菜逼李 在线敲代码