poj3667 Hotel(成段更新+区间合并)
2016-05-11 22:04
344 查看
http://poj.org/problem?id=3667
题意:给你n个房间,m种操作,1操作为查看有没有连续长度为num的房间,若有,则返回其左端点,并将其置为非空;2操作为置空st~st+num-1区间内的房间。
思路:这题就是区间合并和成段更新的完美结合,然后加上懒惰标记的思想。麻烦就麻烦在对各变量的更新查询操作,以及要理解透彻几个变量的意义。ls代表从左数最长连续区间,rs代表从右数最长连续区间,ms代表区间内的最长连续区间。查询时分段查询,更新时按照区间合并的方法。好吧,我承认现在我不怎么会敲长代码。。
题意:给你n个房间,m种操作,1操作为查看有没有连续长度为num的房间,若有,则返回其左端点,并将其置为非空;2操作为置空st~st+num-1区间内的房间。
思路:这题就是区间合并和成段更新的完美结合,然后加上懒惰标记的思想。麻烦就麻烦在对各变量的更新查询操作,以及要理解透彻几个变量的意义。ls代表从左数最长连续区间,rs代表从右数最长连续区间,ms代表区间内的最长连续区间。查询时分段查询,更新时按照区间合并的方法。好吧,我承认现在我不怎么会敲长代码。。
#include <stdio.h> #include <algorithm> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; typedef long long LL; const int N = 50010; const int INF = 1e8; struct line { int l, r; int ls, rs, ms; int con; }tree[4*N]; void build(int i, int l, int r) { tree[i].l = l; tree[i].r = r; tree[i].con = 0;//0表示全空,1表示全满 tree[i].ls = tree[i].rs = tree[i].ms = r-(l-1); if(l == r) { return; } int mid = (l+r) >> 1; build(i*2, l, mid); build(i*2+1, mid+1, r); } int query(int i, int num) { if(tree[i].ls == num && (tree[i].r-tree[i].l+1) == num) { return tree[i].l; } if(tree[i].ms >= num) { if(tree[i].con != -1) { tree[i*2].con = tree[i*2+1].con = tree[i].con; if(tree[i].con == 1) { tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = 0; tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = 0; } else if(tree[i].con == 0) { tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = tree[i*2].r-tree[i*2].l+1; tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = tree[i*2+1].r-tree[i*2+1].l+1; } tree[i].con = -1; } if(tree[i*2].ms >= num) return query(i*2, num); if(tree[i*2].rs+tree[i*2+1].ls >= num) return tree[i*2].r-(tree[i*2].rs-1); if(tree[i*2+1].ms >= num) return query(i*2+1, num); } return 0; } void update(int i, int l, int r, int flag) { if(tree[i].l == l && tree[i].r == r) { //flag为1表示置满,flag为0表示置空 if(flag == 1) tree[i].ls = tree[i].rs = tree[i].ms = 0; else if(flag == 0) tree[i].ls = tree[i].rs = tree[i].ms = r-l+1; tree[i].con = flag; return; } if(tree[i].con != -1) { tree[i*2].con = tree[i*2+1].con = tree[i].con; if(tree[i].con == 1) { tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = 0; tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = 0; } else if(tree[i].con == 0) { tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = tree[i*2].r-tree[i*2].l+1; tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = tree[i*2+1].r-tree[i*2+1].l+1; } tree[i].con = -1; } int mid = (tree[i].l+tree[i].r) >> 1; if(mid >= r) update(i*2, l, r, flag); else if(mid < l) update(i*2+1, l, r, flag); else { update(i*2, l, mid, flag); update(i*2+1, mid+1, r, flag); } if(tree[i*2].con == 0) tree[i].ls = tree[i*2].ms+tree[i*2+1].ls; else tree[i].ls = tree[i*2].ls; if(tree[i*2+1].con == 0) tree[i].rs = tree[i*2+1].ms+tree[i*2].rs; else tree[i].rs = tree[i*2+1].rs; tree[i].ms = max(max(tree[i*2].ms, tree[i*2+1].ms), tree[i*2].rs+tree[i*2+1].ls); tree[i].ms = max(max(tree[i].ls, tree[i].rs), tree[i].ms); if(tree[i].ms == tree[i].r-tree[i].l+1) tree[i].con = 0; else if(tree[i].ms == 0) tree[i].con = 1; else tree[i].con = -1; } int main() { // freopen("in.txt", "r", stdin); int n, m, op, st, num; scanf("%d%d", &n, &m); build(1, 1, n); while(m--) { scanf("%d", &op); if(op == 1) { scanf("%d", &num); st = query(1, num); printf("%d\n", st); if(st) { update(1, st, st+num-1, 1); } } else if(op == 2) { scanf("%d%d", &st, &num); update(1, st, st+num-1, 0); } } return 0; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- POJ1050 最大子矩阵和
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)