POJ 3667 Hotel 线段树 区间合并
题意:
1 输入a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 输入a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间
线段树操作:
update:区间替换 query:询问满足条件的最左端点
#include <cstdio> #include <iostream> #include <algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int MAXN = 55555; int mx[MAXN<<2], lmx[MAXN<<2], rmx[MAXN<<2], cvr[MAXN<<2]; void build(int l, int r, int rt) { mx[rt] = lmx[rt] = rmx[rt] = r - l + 1; cvr[rt] = -1; if(l == r) return; int m = (l + r) >> 1; build(lson); build(rson); } void push_down(int rt, int len) { if(cvr[rt] == -1) return; cvr[rt<<1] = cvr[rt<<1|1] = cvr[rt]; mx[rt<<1] = lmx[rt<<1] = rmx[rt<<1] = cvr[rt]? 0 : len - (len >> 1); mx[rt<<1|1] = lmx[rt<<1|1] = rmx[rt<<1|1] = cvr[rt]? 0 : len >> 1; cvr[rt] = -1; } void push_up(int rt, int len) { lmx[rt] = lmx[rt<<1]; rmx[rt] = rmx[rt<<1|1]; if(lmx[rt] == len - (len >> 1)) lmx[rt] += lmx[rt<<1|1]; if(rmx[rt] == len >> 1) rmx[rt] += rmx[rt<<1]; mx[rt] = max(rmx[rt<<1]+lmx[rt<<1|1], max(mx[rt<<1], mx[rt<<1|1])); } void update(int L, int R, int c, int l, int r, int rt) { if(L <= l && r <= R) { mx[rt] = lmx[rt] = rmx[rt] = c? 0 : r - l + 1; cvr[rt] = c; return; } push_down(rt, r-l+1); int m = (l + r) >> 1; if(m >= L) update(L, R, c, lson); if(m < R) update(L, R, c, rson); push_up(rt, r-l+1); } int query(int w, int l, int r, int rt) { if(mx[rt] < w) return 0; if(l == r) return l; push_down(rt, r-l+1); int m = (l + r) >> 1; if(mx[rt<<1] >= w) return query(w, lson); if(rmx[rt<<1] + lmx[rt<<1|1] >= w) return m - rmx[rt<<1] + 1; return query(w, rson); } int main() { // freopen("in.txt", "r", stdin); int n, m; scanf("%d%d", &n, &m); build(1, n, 1); while(m--) { int t, a, b; scanf("%d%d", &t, &a); if(t == 1) { int p = query(a, 1, n ,1); printf("%d\n", p); if(p) update(p, p+a-1, 1, 1, n, 1); } else { scanf("%d", &b); update(a, a+b-1, 0, 1, n, 1); } } return 0; }