POJ - 3367 -- Hotel

题目来源:http://poj.org/problem?id=3667

线段树中存放六个元素:左右端点left,right。左端点向右延伸后的最大长度cl,右端点向左延伸后的最大长度cr。区间内的最大连续长度maxl。lazy操作的标签add。

从上向下更新,如果覆盖段就打lazy标记,遍历到有lazy标记的线段就将lazy标记pushdown一层。

从下向上两两合并,最大连续长度可能来自左段、右端,或是贯穿左右段。

操作详见代码:

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+10;
int n,m;
struct tree {
    int left, right, maxl, cl, cr, add;
}c[maxn<<2];

int max(int a,int b,int c) {
    return max(a, max(b, c));
}

void build(int id,int l,int r) {
    c[id].left = l;
    c[id].right = r;
    c[id].maxl = c[id].cl = c[id].cr = r - l + 1;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
}

void pushdown(int id) {
    if (c[id].right == c[id].left)return;
    if (c[id].add == -1) {
        c[id].add = 0;
        c[id << 1].maxl = c[id << 1].cl = c[id << 1].cr = 0;
        c[id << 1 | 1].maxl = c[id << 1 | 1].cr = c[id << 1 | 1].cl = 0;
        c[id << 1].add = c[id << 1 | 1].add = -1;
    } else {
        c[id].add = 0;
        c[id << 1].maxl = c[id << 1].cl = c[id << 1].cr = c[id << 1].right - c[id << 1].left + 1;
        c[id << 1 | 1].maxl = c[id << 1 | 1].cr = c[id << 1 | 1].cl = c[id << 1 | 1].right - c[id << 1 | 1].left + 1;
        c[id << 1].add = c[id << 1 | 1].add = 1;
    }
}

int query_max(int id,int v) {
    if (c[id].maxl < v)return 0;
    if (c[id].add != 0)pushdown(id);
    if (c[id << 1].maxl >= v)return query_max(id << 1, v);
    if (c[id << 1].cr + c[id << 1 | 1].cl >= v)return ((c[id].left + c[id].right) >> 1) - c[id << 1].cr + 1;
    return query_max(id << 1 | 1, v);
}

void update(int id,int l,int r,int v) {
    if (c[id].left > r || c[id].right < l)return;
    if (c[id].add)pushdown(id);
    if (c[id].left >= l && c[id].right <= r) {
        c[id].add += v;
        if (v == -1)
            c[id].maxl = c[id].cl = c[id].cr = 0;
        else
            c[id].maxl = c[id].cl = c[id].cr = c[id].right - c[id].left + 1;
        return;
    }
    update(id << 1, l, r, v);
    update(id << 1 | 1, l, r, v);
    if (c[id << 1].cl == c[id << 1].right - c[id << 1].left + 1)
        c[id].cl = c[id << 1].maxl + c[id << 1 | 1].cl;
    else c[id].cl = c[id << 1].cl;
    if (c[id << 1 | 1].cr == c[id << 1 | 1].right - c[id << 1 | 1].left + 1)
        c[id].cr = c[id << 1 | 1].maxl + c[id << 1].cr;
    else c[id].cr = c[id << 1 | 1].cr;
    c[id].maxl = max(c[id << 1].maxl, c[id << 1 | 1].maxl, c[id << 1].cr + c[id << 1 | 1].cl);
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    while (cin >> n >> m) {
        build(1, 1, n);
        for (int i = 1; i <= m; ++i) {
            int flag;
            cin >> flag;
            if (flag == 1) {
                int x;
                cin >> x;
                int t = query_max(1, x);
                cout << t << endl;
                if (t)update(1, t, t + x - 1, -1);
            } else {
                int x, d;
                cin >> x >> d;
                update(1, x, x + d - 1, 1);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/81292599