【poj3667】【线段树】Hotel

来源:互联网 发布:seo网站建设 编辑:程序博客网 时间:2024/05/23 01:51

关于区间合并的线段树。

要求的是满足一个条件的最左边的位置。

所以可以维护一个sum,suml,sumr分别一段区间内空房间的数目,从最左边开始的数目,以及从最右边开始的数目,在pushup的时候需要对区间进行合并,这样在考虑询问的时候,根据维护的信息,优先考虑左边房间就行了。

代码:

#include<cstdio>#include<cstring>#define lson l,m,rt << 1#define rson m + 1,r,rt << 1 | 1using namespace std;const int maxn = 50000 + 10;int suml[maxn<<2],sumr[maxn<<2],sum[maxn<<2];int cover[maxn<<2];int n,m;void init(){freopen("poj3667.in","r",stdin);freopen("poj3667.out","w",stdout);}void build(int l,int r,int rt){sum[rt] = suml[rt] = sumr[rt] = r - l + 1;cover[rt] = -1;if(l == r)return;int m = (l + r) >> 1;build(lson);build(rson);}int max(int a,int b){return a > b ? a : b;}void pushup(int rt,int m){suml[rt] = suml[rt<<1];sumr[rt] = sumr[rt<<1|1];if(suml[rt] == m - (m >> 1))suml[rt] += suml[rt<<1|1];if(sumr[rt] == (m >> 1))sumr[rt] += sumr[rt<<1];sum[rt] = max(suml[rt<<1|1] + sumr[rt<<1],max(sum[rt<<1],sum[rt<<1|1]));}void pushdown(int rt,int m){if(cover[rt] != -1){cover[rt<<1] = cover[rt<<1|1] = cover[rt];sum[rt<<1] = suml[rt<<1] = sumr[rt<<1] = cover[rt] ? 0 : m - (m >> 1);sum[rt<<1|1] = suml[rt<<1|1] = sumr[rt<<1|1] = cover[rt] ? 0 : (m >> 1);cover[rt] = -1;}}void update(int L,int R,int c,int l,int r,int rt){if(L <= l && r <= R){sum[rt] = suml[rt] = sumr[rt] = c ? 0 : r - l + 1;cover[rt] = c;return;}pushdown(rt,r - l + 1);int m = (l + r) >> 1;if(L <= m)update(L,R,c,lson);if(m < R)update(L,R,c,rson);pushup(rt,r - l + 1);}int query(int tot,int l,int r,int rt){if(l == r)return l;pushdown(rt,r - l + 1);int m = (l + r) >> 1;if(sum[rt<<1] >= tot)return query(tot,lson);else if(sumr[rt<<1] + suml[rt<<1|1] >= tot)return m - sumr[rt<<1] + 1;return query(tot,rson);}void readdata(){memset(cover,-1,sizeof(cover));scanf("%d%d",&n,&m);build(1,n,1);for(int i = 1;i <= m;i++){int op,d;scanf("%d",&op);if(op == 1){scanf("%d",&d);if(sum[1] < d)puts("0");else{int tmp = query(d,1,n,1);printf("%d\n",tmp);update(tmp,tmp + d - 1,1,1,n,1);}}else{int x;scanf("%d%d",&x,&d);update(x,x + d - 1,0,1,n,1);}}}int main(){init();readdata();return 0;}


原创粉丝点击