POJ 3667 Hotel(线段树区间合并)

来源:互联网 发布:征服者rd88升级软件 编辑:程序博客网 时间:2024/06/06 11:39

题意:

一家旅馆有N(1 ≤ N ≤ 50000)间房间,并且所有的房间都是连续排列在同一边,现在每个观光团需要入住房间,要求房间的编号为连续的r...r+Di1,并且r是最小的;
参观者同样可能退房,并且他们每次退房都是编号为Xi...Xi+Di1 (1XiNDi+1)的房间。
现在有两种操作:
1. 1 a 每个观光团需要入住a间编号连续的房间
2. 2 a b 观光者需要退房间,其中房间编号是 a...a+b1
要求对于每次询问,输出为观光团分配数目为a的房间中编号最小的房间编号

解析:

利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是答案,同时因为需要求出连续区间的最大长度,因此每次pushUp时都将左右区间合并,
lsum维护左区间的最大长度,
rsum维护右区间的最大长度,
msum维护区间1...N中的最大连续区间长度,
cover标志对应区间是否为空。

my code

#include <cstdio>#include <cstring>#include <algorithm>#define ls o<<1#define rs o<<1|1#define lson ls, L, M#define rson rs, M+1, Rusing namespace std;const int N = 50005;int cover[N<<2]; //懒惰标记 -1无操作,0区间为空,1区间为满int lsum[N<<2], rsum[N<<2], msum[N<<2];int n, m;void pushDown(int o, int L, int R) {    if(cover[o] != -1) {        int M = (L + R)/2;        cover[ls] = cover[rs] = cover[o];        lsum[ls] = rsum[ls] = msum[ls] = cover[o] ? 0 : (M - L + 1);        lsum[rs] = rsum[rs] = msum[rs] = cover[o] ? 0 : (R - M);        cover[o] = -1;    }}void pushUp(int o, int L, int R) {    int M = (L + R)/2;    int len1 = M - L + 1, len2 = R - M;    lsum[o] = lsum[ls]; rsum[o] = rsum[rs];    if(lsum[o] == len1) lsum[o] += lsum[rs];    if(rsum[o] == len2) rsum[o] += rsum[ls];    msum[o] = max(msum[ls], max(msum[rs],  rsum[ls] + lsum[rs]));    if(cover[ls] == cover[rs]) cover[o] = cover[ls];    else cover[o] = -1;}void modify(int o, int L, int R, int ql, int qr, int val) {    if(ql <= L && R <= qr) {        cover[o] = val;        lsum[o] = rsum[o] = msum[o] = (val) ? 0 : (R-L+1);        return ;    }    pushDown(o, L, R);    int M = (L + R)/2;    if(ql <= M) modify(lson, ql, qr, val);    if(qr > M) modify(rson, ql, qr, val);    pushUp(o, L, R);}int query(int o, int L, int R, int need) {    if(L == R) return L;    pushDown(o, L, R);    int M = (L + R)/2;    if(msum[ls] >= need)        return query(lson, need);    else if(lsum[rs] + rsum[ls] >= need)        return M - rsum[ls] + 1;    else return query(rson, need);}void build(int o, int L, int R) {    cover[o] = -1;    lsum[o] = rsum[o] = msum[o] = R - L + 1;    if(L == R) return ;    int M = (L + R)/2;    build(lson);    build(rson);}int main() {    while(scanf("%d%d", &n, &m) != EOF) {        build(1, 1, n);        int oper, ql, qr, need;        while(m--) {            scanf("%d", &oper);            if(oper == 1) {                scanf("%d", &need);                if(msum[1] < need) {                    puts("0");                    continue;                }                ql = query(1, 1, n, need);                printf("%d\n", ql);                qr = ql + need - 1;                modify(1, 1, n, ql, qr, 1);            }else {                scanf("%d%d", &ql, &need);                qr = ql + need - 1;                modify(1, 1, n, ql, qr, 0);            }        }    }    return 0;}
0 0
原创粉丝点击