poj 3667 Hotel(区间合并)

来源:互联网 发布:macbook u盘接口知乎 编辑:程序博客网 时间:2024/06/05 15:20

题目链接; poj 3667 Hotel

题意:有n个房间,m组询问,询问中第一个数字表示方式,1表示住人,后面的那个数表示住店的人数,2表示清空,后面跟着两个数字票p,q,表示从第p个房间开始数,q个房间清空,我们尽可能的要使人住在左边的房间且房间数必须连续,问你住店时从那个房间开始住;

#include<iostream>#include<cstdio>#define maxn 55555#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;int col[maxn<<2];//延迟标记,值为1时表示住人,0表示走人,-1表示此区间没有访问过,不用向下更新int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];//lsum表示区间从最左边开始到右边的连续空位,rsum为区间从最右边开始到左边的连续空位,msum表示此区间最大的连续空间void pushdown(int rt,int m){    if(col[rt]!=-1) //此区间之前被更新过,所以要向下更新    {       col[rt<<1]=col[rt<<1|1]=col[rt];//把此区间的的信息传递给它的子区间       lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=col[rt]?0:(m-(m>>1));//左儿子,两种情况,一种col为1表示住人,空位变为0,否则就是走人,空位等于区间长度       lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=col[rt]?0:(m>>1);//情况与左儿子相同       col[rt]=-1; //向下女更新过了,取消标记    }}void pushup(int rt, int m){    lsum[rt]=lsum[rt<<1]; //父区间的从左开始的最大空位等于左儿子从左开始的最大空位长度    rsum[rt]=rsum[rt<<1|1];//右儿子情况与左儿子差不多    if(lsum[rt]==(m-(m>>1))) lsum[rt]+=lsum[rt<<1|1];//若左儿子的最大左空间等于区间长度,则要加上右儿子的左空间,最为父区间最大左空间的长度    if(rsum[rt]==(m>>1))   rsum[rt]+=rsum[rt<<1];//父区间的最大有空间与左儿子思想相同    msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);//然后更新父区间整个连续空间的最大值,可能左儿子空间的最大,也可能是右儿子,也可能是左右儿子连通,他们的空间和最大}void build(int l,int r,int rt){    lsum[rt]=rsum[rt]=msum[rt]=r-l+1;//初始空间大小为区间长度    col[rt]=-1;//表示没有被标记过    if(l==r) return ;    int m=(l+r)>>1;    build(lson);    build(rson);}int query(int p,int l,int r,int rt){    if(l==r) return l;    pushdown(rt,r-l+1); //向下更新子节点    int m=(l+r)>>1;    if(p<=msum[rt<<1]) return query(p,lson); //如果所需空间数比左儿子的空间数小,则住在左区间    else if(rsum[rt<<1]+lsum[rt<<1|1]>=p) return m-rsum[rt<<1]+1;//若是比左儿子的右区间与右儿子左区间的和小,则直接返回左儿子右区间的最左端    return query(p,rson);//否则在右儿子里找}void update(int L,int R,int c,int l,int r,int rt){    if(L<=l&&r<=R)    {        msum[rt]=lsum[rt]=rsum[rt]=c?0:r-l+1; //c为1表示住人,0,表示走人,住人则和变为0,走人则赋为区间长度        col[rt]=c;//改变区间的更新标志        return ;    }    pushdown(rt,r-l+1);    int m=(l+r)>>1;    if(L<=m) update(L,R,c,lson);//往左半部分找    if(R>m)  update(L,R,c,rson);//往右半部分找    pushup(rt,r-l+1);}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        build(1,n,1);        int op,a,b;        while(m--)        {            scanf("%d",&op);            if(op==1)            {                scanf("%d",&a);                if(msum[1]<a) printf("0\n"); //若开始总区间的最大空位小于所需空位,直接输出0                else                {                    int p = query(a,1,n,1);                    printf("%d\n",p);                    update(p,p+a-1,1,1,n,1);                }            }            else            {                scanf("%d%d",&a,&b);                update(a,a+b-1,0,1,n,1);            }        }    }    return 0;}


0 0
原创粉丝点击