poj 3667 Hotel 区间合并

来源:互联网 发布:台湾士林夜市 知乎 编辑:程序博客网 时间:2024/05/16 14:17
//poj 3667 Hotel 区间合并////题目大意:////[1,N]区间内开始为空,有两种操作//1) 1 a 找到长度为a的区间,并且尽量开头靠左,返回最左的位置//并check in.//2) 2 a b 将[a,b-1]区间check out.////解题思路:////线段树-区间合并,对于每个节点记录三个值.//lsum表示该节点区间从左边开始的空的区间长度//rsum表示该节点区间从右到左开始空的区间长度//sum表示该节点区间最长的空的区间长度//进行push_down的操作的时候//对于laz标记,看该区间是何标记,并将其两个子区间标记为相应值//对于push_up操作.更新其节点的三个值//lsum[rt] 置为左儿子的lsum值.如果左儿子该区间的lsum就是左儿子//的区间长度,那么就可以加上右儿子的lsum值了//rsum[rt] 置为右儿子的rsum值.如果右儿子该区间的rsum就是右儿子//的区间长度,那么就可以加上左儿子的rsum值了//sum[rt] 是左儿子的sum的值,右儿子的sum的值,中间一段sum的值的//最大取值.//关键的操作感觉就是这俩.////感悟:////线段树的区间合并,维护三个值,前驱,后驱,整个区间的值.然后就是//push_up(),push_down()操作.恩...估计还是标记的处理...见识了初步的//继续加油吧~~~#include <cstring>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <string>#include <vector>#include <queue>#define For(x,a,b,c) for (int x = a; x <= b; x += c)#define Ffor(x,a,b,c) for (int x = a; x >= b; x -= c)#define cls(x,a) memset(x,a,sizeof(x))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double EPS = 1e-10;const int MAX_N = 50000 + 8;const double INF = 1e9;int N,M;struct IntervelTree{#define ls(x) (x << 1)#define rs(x)(x << 1 | 1)int sum[MAX_N<<2];int lsum[MAX_N<<2];int rsum[MAX_N<<2];int laz[MAX_N<<2];//int ql,qr;int v;void build(int rt,int L,int R){sum[rt] = lsum[rt] = rsum[rt] = R - L + 1;laz[rt] = -1;if (L == R)return ;int M = (L + R) >> 1;build(ls(rt),L,M);build(rs(rt),M+1,R);}void push_down(int rt,int M){if (laz[rt] != -1){laz[ls(rt)] = laz[rs(rt)] = laz[rt];sum[ls(rt)] = lsum[ls(rt)] = rsum[ls(rt)] = laz[rt] ? 0 : M - (M >> 1);sum[rs(rt)] = lsum[rs(rt)] = rsum[rs(rt)] = laz[rt] ? 0 : M >> 1;laz[rt] = -1;}}void push_up(int rt,int M){lsum[rt] = lsum[ls(rt)];rsum[rt] = rsum[rs(rt)];if (lsum[rt] == M - (M >> 1)) lsum[rt] += lsum[rs(rt)];if (rsum[rt] == (M >> 1))rsum[rt] += rsum[ls(rt)];sum[rt] = max(rsum[ls(rt)] + lsum[rs(rt)], max(sum[ls(rt)],sum[rs(rt)]));}int query(int rt,int L,int R,int q){if (L == R)return L;push_down(rt,R - L + 1);int M =(L + R) >> 1;if (sum[ls(rt)] >= q)return query(ls(rt),L,M,q);else if (rsum[ls(rt)] + lsum[rs(rt)] >= q) return M - rsum[ls(rt)] + 1;elsereturn query(rs(rt),M+1,R,q);}void update(int rt,int L,int R,int ql,int qr,int v){if (ql <= L && R <= qr){lsum[rt] = rsum[rt] = sum[rt] =v ? 0 : R - L + 1;laz[rt] = v;return ;}push_down(rt,R - L + 1);int M = (L + R) >> 1;if (ql <= M)update(ls(rt),L,M,ql,qr,v);if (M < qr)update(rs(rt),M+1,R,ql,qr,v);push_up(rt,R - L + 1);}}it;void input(){it.build(1,1,N);for (int i =  0 ; i < M; i ++){int x;scanf("%d",&x);if (x == 1){int a;scanf("%d",&a);if (it.sum[1] < a){puts("0");continue;}int p = it.query(1,1,N,a);printf("%d\n",p);it.update(1,1,N,p,p+a-1,1);}else{int a,b;scanf("%d%d",&a,&b);it.update(1,1,N,a,a+b-1,0);}}}int main(){//freopen("1.in","r",stdin);while(scanf("%d%d",&N,&M)!=EOF){input();}}

0 0
原创粉丝点击