【随便做做|线段树】POJ3667 Hotel

来源:互联网 发布:淘宝买家可以延长收货 编辑:程序博客网 时间:2024/06/06 13:00
  • 题意:1n的房间,初始为空。有两种操作:
    • 操作1: 需要选出连续一段的若干个房间入住,输出起点位置,选不出则输出0
    • 操作2: 将从left开始的连续size个房间清空。
    • 数据规模: n,m50000
  • 题解:用线段树|区间树维护。节点主要维护三个值:{ml,mr,md},分别表示从左端开始连续,从右端开始向左连续,整段区间连续的最长子区段的长度。对第一种操作,只需要无脑query,然后对query到的结果([from,to])进行更新即可;对第二种操作,当然就和上述更新差不多辣~
  • P.S. 为了保证按照上述方法维护时线段树的单次操作复杂度,需要加入lazy操作,呃。。。胡乱地搞一下,就可以通过了。。。
/* **********************************************    File Name: 3667.cpp    Auther: zhengdongjian@tju.edu.cn    Created Time: 2015/9/22 星期二 下午 9:16:53*********************************************** */#include <map>#include <set>#include <list>#include <cmath>#include <ctime>#include <deque>#include <queue>#include <stack>#include <bitset>#include <cstdio>#include <string>#include <vector>#include <climits>#include <complex>#include <cstdlib>#include <cstring>#include <fstream>#include <sstream>#include <utility>#include <iostream>#include <algorithm>#include <functional>using namespace std;typedef long long ll;typedef pair<int, int> P;const int MAX = 50007;struct Node {    int ml;    int mr;    int md;    int lazy;} room[MAX << 2];void build(int root, int left, int right) {    room[root].ml = room[root].mr = room[root].md = right - left + 1;    room[root].lazy = 0;    if (left == right) {        return;    }    int mid = (left + right) >> 1;    build(root << 1, left, mid);    build(root << 1 | 1, mid + 1, right);}void pushup(int root, int left, int right) {    int ls = root << 1;    int rs = root << 1 | 1;    int mid = (left + right) >> 1;    room[root].ml = room[ls].ml;    if (room[ls].ml == mid - left + 1) {        room[root].ml += room[rs].ml;    }    room[root].mr = room[rs].mr;    if (room[rs].mr == right - mid) {        room[root].mr += room[ls].mr;    }    room[root].md = max(max(room[ls].md, room[rs].md), max(room[root].ml, room[root].mr));    if (room[ls].mr + room[rs].ml > room[root].md) {        room[root].md = room[ls].mr + room[rs].ml;    }}void pushdown(int root, int left, int right) {    //printf("pushdown (%d, %d)\n", left, right);    if (left == right) {        room[root].ml = room[root].mr = room[root].md = (~room[root].lazy) ? 0 : 1;        room[root].lazy = 0;        return;    }    room[root << 1].lazy = room[root << 1 | 1].lazy = room[root].lazy;    if (~room[root].lazy) {        room[root << 1].ml = room[root << 1].mr = room[root << 1].md = 0;        room[root << 1 | 1].ml = room[root << 1 | 1].mr = room[root << 1 | 1].md = 0;    } else {        int mid = (left + right) >> 1;        room[root << 1].ml = room[root << 1].mr = room[root << 1].md = mid - left + 1;        room[root << 1 | 1].ml = room[root << 1 | 1].mr = room[root << 1 | 1].md = right - mid;    }    room[root].lazy = 0;}void check_out(int root, int left, int right, int from, int to) {    //printf("check out (%d, %d) with %d, %d...", left, right, from, to);    if (to < left || from > right) {        //puts("not match");        return;    } else if (from <= left && to >= right) {        //puts("all match");        room[root].ml = room[root].mr = room[root].md = right - left + 1; //all clear        room[root].lazy = -1;        return;    }    //puts("match some");    if (room[root].lazy != 0) {        pushdown(root, left, right);    }    int mid = (left + right) >> 1;    check_out(root << 1, left, mid, from, to);    check_out(root << 1 | 1, mid + 1, right, from, to);    pushup(root, left, right);}int query(int root, int left, int right, int cnt) {    //printf("query %d, %d, %d (%d, %d, %d)...", left, right, cnt, room[root].ml, room[root].mr, room[root].md);    if (room[root].md < cnt) {        //printf("(%d, %d, %d) not enough!\n", room[root].ml, room[root].mr, room[root].md);        return 0;    }    if (left == right) {        //printf("equal to one\n");        return left;    }    //puts("to judge:");    if (room[root].lazy != 0) {        pushdown(root, left, right);    }    int mid = (left + right) >> 1;    int le = query(root << 1, left, mid, cnt);    if (le > 0) {        //printf("get left\n");        return le;    }     if (room[root << 1].mr + room[root << 1 | 1].ml >= cnt) {        //printf("get mid\n");        return mid - room[root << 1].mr + 1;    }    //printf("get right\n");    return query(root << 1 | 1, mid + 1, right, cnt);}void check_in(int root, int left, int right, int from, int to) {    //printf("check in %d, %d, with %d, %d...", left, right, from, to);    if (to < left || from > right) {        //printf("match failed!\n");        return;    } else if (from <= left && to >= right) {        //puts("match all!");        room[root].lazy = 1;        room[root].ml = room[root].mr = room[root].md = 0;        return;    }    //puts("match some");    if (room[root].lazy) {        pushdown(root, left, right);    }    int mid = (left + right) >> 1;    check_in(root << 1, left, mid, from, to);    check_in(root << 1 | 1, mid + 1, right, from, to);    pushup(root, left, right);    //printf("and update (%d, %d) to %d, %d, %d\n", left, right, room[root].ml, room[root].mr, room[root].md);}void debug(int root, int left, int right) {    printf("(%d, %d) => (%d, %d, %d, %d)\n", left, right, room[root].ml, room[root].mr, room[root].md, room[root].lazy);    if (left == right) {        return;    }    int mid = (left + right) >> 1;    debug(root << 1, left, mid);    debug(root << 1 | 1, mid + 1, right);}int main() {    int n, m;    while (~scanf(" %d %d", &n, &m)) {        build(1, 1, n);        int op, sz, le;        while (m--) {            scanf(" %d", &op);            if (op == 1) {                scanf(" %d", &sz);                le = query(1, 1, n, sz);                //printf("le = %d\n", le);                if (le) check_in(1, 1, n, le, le + sz - 1);                printf("%d\n", le);            } else {                scanf(" %d %d", &le, &sz);                check_out(1, 1, n, le, le + sz - 1);            }            //debug(1, 1, n);        }    }    return 0;}
0 0