首页 > 代码库 > POJ 3667 Hotel(线段树)
POJ 3667 Hotel(线段树)
POJ 3667 Hotel
题目链接
题意:有n个房间,现在有两个操作
1、找到连续长度a的空房间,入住,要尽量靠左边,如果有输出最左边的房间标号,如果没有输出0
2、清空[a, a + b - 1]的房间
思路:线段树的区间合并,记录下左边连续最长和右边连续最长空房间,和每一段的最大值,这样pushup的时候就是进行区间合并,注意查询的时候由于是要尽量左,所以先查左孩子,在查横跨左右的,在查右孩子
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) const int N = 50005; int n, m; struct Node { int l, r, lsum, rsum, sum, sumv, lazy; int size() {return r - l + 1;} void gao(int v) { lazy = v; if (v) lsum = rsum = sum = 0; else lsum = rsum = sum = r - l + 1; sumv = l; } } node[N * 4]; void pushup(int x) { if (node[lson(x)].lsum == node[lson(x)].size()) node[x].lsum = node[lson(x)].lsum + node[rson(x)].lsum; else node[x].lsum = node[lson(x)].lsum; if (node[rson(x)].rsum == node[rson(x)].size()) node[x].rsum = node[lson(x)].rsum + node[rson(x)].rsum; else node[x].rsum = node[rson(x)].rsum; node[x].sum = node[lson(x)].sum; node[x].sumv = node[lson(x)].sumv; if (node[x].sum < node[lson(x)].rsum + node[rson(x)].lsum) { node[x].sum = node[lson(x)].rsum + node[rson(x)].lsum; node[x].sumv = node[lson(x)].r - node[lson(x)].rsum + 1; } if (node[x].sum < node[rson(x)].sum) { node[x].sum = node[rson(x)].sum; node[x].sumv = node[rson(x)].sumv; } } void pushdown(int x) { if (node[x].lazy != -1) { node[lson(x)].gao(node[x].lazy); node[rson(x)].gao(node[x].lazy); node[x].lazy = -1; } } void build(int l, int r, int x = 0) { node[x].l = l; node[x].r = r; node[x].lazy = -1; if (l == r) { node[x].lsum = node[x].rsum = node[x].sum = 1; return; } int mid = (l + r) / 2; build(l, mid, lson(x)); build(mid + 1, r, rson(x)); pushup(x); } void add(int l, int r, int v, int x = 0) { if (node[x].l >= l && node[x].r <= r) { node[x].gao(v); return; } int mid = (node[x].l + node[x].r) / 2; pushdown(x); if (l <= mid) add(l, r, v, lson(x)); if (r > mid) add(l, r, v, rson(x)); pushup(x); } int query(int v, int x = 0) { if (node[x].l == node[x].r) { if (node[x].sum >= v) return node[x].sumv; return 0; } pushdown(x); int ans = 0; if (node[lson(x)].sum >= v) ans = query(v, lson(x)); else if (node[lson(x)].rsum + node[rson(x)].lsum >= v) ans = node[lson(x)].r - node[lson(x)].rsum + 1; else if (node[rson(x)].sum >= v) ans = query(v, rson(x)); pushup(x); return ans; } int main() { while (~scanf("%d%d", &n, &m)) { build(1, n); int op, a, b; while (m--) { scanf("%d%d", &op, &a); if (op == 2) { scanf("%d", &b); add(a, a + b - 1, 0); } else { int tmp = query(a); printf("%d\n", tmp); if (tmp == 0) continue; add(tmp, tmp + a - 1, 1); } } } return 0; }
POJ 3667 Hotel(线段树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。