您的位置:首页 > 理论基础 > 数据结构算法

poj3667(线段树区间合并)

2014-01-09 20:23 603 查看
题目链接:poj3667

/*poj 3667 Hotel 线段树区间合并
题意:
操作1:询问是否有连续x间房间可以住,输出最左端的房间位置
操作2:顾客退房,将房间清空,表示没有人住

思路:
利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,
并且对应区间中最左边的端点就是ans,同时因为需要求出连续区间的最大长度,
因此每次PushUp时都将左右区间合并,lsum维护左区间的最大长度,rsum维护右区间的最大长度,
sum维护区间1…N中的最大连续区间长度,cover标志对应区间是否为空(没有住客)
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int N = 150000;

int cover[N<<2];
int llen[N<<2],rlen[N<<2],mlen[N<<2];
void build(int l, int r, int rt)
{
llen[rt] = rlen[rt] = mlen[rt] = r - l + 1;
cover[rt] = -1;
if(l == r) return;
int m = (l + r) >> 1;
build(lson);
build(rson);
}
void pushdown(int rt, int m)//更新子节点
{
if(cover[rt] != -1)
{
llen[rt<<1] = rlen[rt<<1] = mlen[rt<<1] = cover[rt] ? 0 : m - (m>>1);
llen[rt<<1|1] = rlen[rt<<1|1] = mlen[rt<<1|1] = cover[rt] ? 0 : (m>>1);
cover[rt<<1] = cover[rt<<1|1] = cover[rt];
cover[rt] = -1;
}
}
void pushup(int rt, int m)//更新父节点
{
llen[rt] = llen[rt<<1];
rlen[rt] = rlen[rt<<1|1];
if(llen[rt] == m - (m>>1)) llen[rt] += llen[rt<<1|1];
if(rlen[rt] == (m>>1)) rlen[rt] += rlen[rt<<1];
mlen[rt] = max(llen[rt<<1|1] + rlen[rt<<1], max(mlen[rt<<1], mlen[rt<<1|1]));
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L <= l && r <= R)
{
llen[rt] = rlen[rt] = mlen[rt] = c?0:r-l+1;
cover[rt] = c;
return ;
}
pushdown(rt, r-l+1);
int m = (l + r) >> 1;
if(L <= m) update(L, R, c, lson);
if(m < R) update(L, R, c, rson);
pushup(rt, r-l+1);
}
int query(int num, int l, int r, int rt)
{
if(l == r) return l;
pushdown(rt, r-l+1);
int m = (l+r) >> 1;
if(mlen[rt<<1] >= num) // 左连续区间长度
return query(num, lson);
else if(rlen[rt<<1] + llen[rt<<1|1] >= num) // 左区间右半部分与右区间左半部分长度
return m - rlen[rt<<1] + 1;
return query(num, rson);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
build(1, n ,1);
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op == 1)
{
scanf("%d",&x);
if(mlen[1] < x) puts("0");
else
{
int ans = query(x, 1, n, 1);
printf("%d\n",ans);
update(ans, ans + x - 1, 1, 1, n, 1);
}
}
if(op == 2)
{
scanf("%d%d",&x,&y);
update(x, x+y-1, 0, 1, n, 1);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息