POJ_3667

    第一次接触区间合并的问题,更多区间合并的问题可以参考胡浩的博客http://www.notonlysuccess.com/index.php/segment-tree-complete/

    既然要查询是否存在一个长为d的连续空区间,那么我们至少要记录对于每个区间而言,其中的最长的连续空区间是多大,这个用mc[](max contiguous)表示。同时在查找的过程中,连续空区间有三种形式,在左子树,在右子树,或者横跨两棵子树。当然我们要优先找左子树,最后再找右子树,那么中间的这个横跨的怎么办呢?于是我们可以引入lc[](left contiguous)表示一个区间从左边开始连续最长的区间是多少,rc[](right contiguous)表示一个区间从右边开始连续最长的区间是多少,如果rc[left son]+lc[right son]>=d,那么就说明存在这样一个横跨两棵子树的区间,由于我们知道左子树最右边点的坐标x,那么这个连续空区间的第一个位置自然就是x-rc[left son]+1。

    查找功能实现了之后,剩下的就是染色了,如果是住进去就都染成0,如果是搬出来就都染成1。

    此外,我们在染色之后只要更新父节点mc[]、lc[]、rc[]的状态的,这时对于父节点这个区间,最长的连续区间除了左子树中最长的和右子树中最长的,还要将横跨两棵子树的最长的连续区间也纳入考虑的范围。

#include<stdio.h>
#include<string.h>
#define MAXD 50010
int N, M, mc[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], flag[4 * MAXD];
int getmax(int x, int y)
{
return x > y ? x : y;
}
void build(int cur, int x, int y)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
mc[cur] = lc[cur] = rc[cur] = y - x + 1;
flag[cur] = -1;
if(x == y)
return ;
build(ls, x, mid);
build(rs, mid + 1, y);
}
void pushdown(int cur, int x, int y)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(flag[cur] != -1)
{
flag[ls] = flag[rs] = flag[cur];
mc[ls] = lc[ls] = rc[ls] = (flag[cur] ? 0 : mid - x + 1);
mc[rs] = lc[rs] = rc[rs] = (flag[cur] ? 0 : y - mid);
flag[cur] = -1;
}
}
void update(int cur, int x, int y)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
mc[cur] = getmax(mc[ls], mc[rs]);
mc[cur] = getmax(mc[cur], rc[ls] + lc[rs]);
lc[cur] = lc[ls] + (lc[ls] == mid - x + 1 ? lc[rs] : 0);
rc[cur] = rc[rs] + (rc[rs] == y - mid ? rc[ls] : 0);
}
int Search(int cur, int x, int y, int d)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x == y)
return x;
pushdown(cur, x, y);
if(mc[ls] >= d)
return Search(ls, x, mid, d);
else if(rc[ls] + lc[rs] >= d)
return mid - rc[ls] + 1;
else
return Search(rs, mid + 1, y, d);
}
void color(int cur, int x, int y, int s, int t, int c)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x >= s && y <= t)
{
flag[cur] = c;
mc[cur] = lc[cur] = rc[cur] = (c ? 0 : y - x + 1);
return ;
}
pushdown(cur, x, y);
if(mid >= s)
color(ls, x, mid, s, t, c);
if(mid + 1 <= t)
color(rs, mid + 1, y, s, t, c);
update(cur, x, y);
}
void solve()
{
int i, j, k, r, d, x;
for(i = 0; i < M; i ++)
{
scanf("%d", &k);
if(k == 1)
{
scanf("%d", &d);
if(mc[1] < d)
printf("0\n");
else
{
r = Search(1, 1, N, d);
printf("%d\n", r);
color(1, 1, N, r, r + d - 1, 1);
}
}
else
{
scanf("%d%d", &x, &d);
color(1, 1, N, x, x + d - 1, 0);
}
}
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
build(1, 1, N);
solve();
}
return 0;
}


posted on 2012-03-29 22:19  Staginner  阅读(450)  评论(0编辑  收藏  举报