POJ 3667 Hotel 线段树区间合并

线段树的区间合并,其中lsum代表区间左边最大连续长度,rsum代表区间最大连续长度,msum代表区间

最大连续长度。因为本题是查询连续区间的左端点,那么如果左儿子满足条件,就继续查询左儿子,左儿

子不满足条件,就判断左儿子的rsum + 右儿子的lsum是不是满足条件,最后才查询右儿子。

 

/*Accepted    2236K    594MS    C++    2574B    2012-08-21 12:15:23*/

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<algorithm>

using namespace std;

#define lson l, mid, rt << 1

#define rson mid + 1, r, rt << 1 | 1



const int MAXN = 50050;

int msum[MAXN << 2], lsum[MAXN << 2], rsum[MAXN << 2];

int col[MAXN << 2];



void PushDown(int l, int r, int rt)

{

    int mid = l + r >> 1;

    if(col[rt] != -1)

    {

        col[rt << 1] = col[rt << 1 | 1] = col[rt];

        msum[rt << 1] = lsum[rt << 1] = rsum[rt << 1] = col[rt] ? 0 : mid - l + 1;

        msum[rt << 1 | 1] = lsum[rt << 1 | 1] = rsum[rt << 1 | 1]

        = col[rt] ? 0 : r - mid;

        col[rt] = -1;

    }

}



void PushUp(int l, int r, int rt)

{

    int mid = l + r >> 1;

    lsum[rt] = lsum[rt << 1];

    rsum[rt] = rsum[rt << 1 | 1];

    if(lsum[rt] == mid - l + 1) lsum[rt] += lsum[rt << 1 | 1];

    if(rsum[rt] == r - mid) rsum[rt] += rsum[rt << 1];

    msum[rt] = max(lsum[rt << 1 | 1] + rsum[rt << 1],

                   max(msum[rt << 1], msum[rt << 1 | 1]));

}



void build(int l, int r, int rt)

{

    int mid = l + r >> 1;

    msum[rt] = lsum[rt] = rsum[rt] = r - l + 1;

    col[rt] = -1;

    if(l == r) return;

    build(lson);

    build(rson);

}



void update(int L, int R, int c, int l, int r, int rt)

{

    int mid = l + r >> 1;

    if(L <= l && r <= R)

    {

        msum[rt] = lsum[rt] = rsum[rt] = c ? 0 : r - l + 1;

        col[rt] = c;

        return;

    }

    PushDown(l, r, rt);

    if(L <= mid) update(L, R, c, lson);

    if(R > mid) update(L, R, c, rson);

    PushUp(l, r, rt);

}



int query(int w, int l, int r, int rt)

{

    int mid = l + r >> 1;

    if(l == r) return l;

    PushDown(l, r, rt);

    if(msum[rt << 1] >= w) return query(w, lson);

    else if(lsum[rt << 1 | 1] + rsum[rt << 1] >= w)

        return mid - rsum[rt << 1] + 1;

    return query(w, rson);

}



int main()

{

    int n, m;

    while(scanf("%d%d", &n, &m) == 2)

    {

        build(1, n, 1);

        while(m --)

        {

            int op, a, b;

            scanf("%d", &op);

            if(1 == op)

            {

                scanf("%d", &a);

                if(a > msum[1]) puts("0");

                else

                {

                    int p = query(a, 1, n, 1);

                    printf("%d\n", p);

                    update(p, p + a - 1, 1, 1, n, 1);

                }

            }

            else

            {

                scanf("%d%d", &a, &b);

                update(a, a + b - 1, 0, 1, n, 1);

            }

        }

    }

    return 0;

}

 

 

 

你可能感兴趣的:(poj)