POJ 3667 Hotel

刚开始是照着小媛姐的代码来写的,因为感觉自己对细节的处理认识不是很深刻。。

但是小媛姐把懒惰标记作为区间是否被0/1覆盖来做的,

也就是说懒惰标记会被pushup

于是A掉了以后打算用不pushup懒惰标记的方法写,

写了一下午= =。。。


于是乎总结了下懒惰标记和区间是否被覆盖的区别。。

第一个区别是区间被覆盖的标记需要pushup,而懒惰标记在pushdown的时候需要赋值为-1;

第二个区别就是在update的时候,如果需要懒惰标记来计算节点的值的时候,懒惰标记是不能用来计算的,

改进的方法就是通过l,r来判断。。


从褚神那得知#define 是可以替代含有空格串的,于是乎#define canshu int l,int r,int rt....


这是区间覆盖的标记的代码:

#include<stdio.h>
#define ls rt*2
#define rs rt*2+1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define canshu int l,int r,int rt
#define X 50010
int tr[X*4],lv[X*4],rv[X*4],sum[X*4];
void tclear(int rt,int s){
    sum[rt]=lv[rt]=rv[rt]=s;
}
void build(canshu){
    tr[rt]=0;
    tclear(rt,r-l+1);
    if(l==r)return ;
    int mid=l+r>>1;
    build(lson);
    build(rson);
}
int max(int a,int b,int c){
    if(a>=b&&a>=c)return a;
    if(b>=a&&b>=c)return b;
    if(c>=a&&c>=b)return c;
}
void pushup(int rt){
    tr[rt]=tr[ls]==tr[rs]?tr[ls]:-1;
    lv[rt]=lv[ls]+(tr[ls]==0?lv[rs]:0);
    rv[rt]=rv[rs]+(tr[rs]==0?rv[ls]:0);
    sum[rt]=max(sum[ls],sum[rs],rv[ls]+lv[rs]);
}
void pushdown(canshu){
    if(tr[rt]!=-1){
        int mid=l+r>>1;
        tr[ls]=tr[rs]=tr[rt];
        tclear(ls,(!tr[rt])*(mid-l+1));
        tclear(rs,(!tr[rt])*(r-mid));
    }
}
int ll,rr,c;
void update(canshu){
    if(ll<=l&&rr>=r){
        tr[rt]=c;
        tclear(rt,(!c)*(r-l+1));
        //printf("updt: l=%d r=%d  flag=%d sum=%d lv=%d rv=%d\n",l,r,tr[rt],sum[rt],lv[rt],rv[rt]);
        return ;
    }
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(ll<=mid)update(lson);
    if(rr> mid)update(rson);
    pushup(rt);
    //rintf("updt: l=%d r=%d  flag=%d sum=%d lv=%d rv=%d\n",l,r,tr[rt],sum[rt],lv[rt],rv[rt]);
}
int que(canshu){
    //printf("que: l=%d r=%d  flag=%d sum=%d lv=%d rv=%d\n",l,r,tr[rt],sum[rt],lv[rt],rv[rt]);
    if(tr[rt]==0){
        if(sum[rt]>=c)return l;
        return -1;
    }
    if(tr[rt]==1)return -1;
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(sum[ls]>=c)return que(lson);
    else if(rv[ls]+lv[rs]>=c)
        return mid-rv[ls]+1;
    else if(sum[rs]>=c)return que(rson);
    return -1;
}
int main(){
    freopen("hotel.2.in","r",stdin);
    freopen("out2.txt","w",stdout);
    int f,pos,d,n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    while(m--){
        scanf("%d",&f);
        if(f==1){
            scanf("%d",&c);
            pos=que(1,n,1);
            if(pos==-1){printf("0\n");continue;}
            ll=pos;rr=pos+c-1;c=1;
            update(1,n,1);
            printf("%d\n",pos);
        }
        else {
            scanf("%d%d",&pos,&c);
            ll=pos;rr=pos+c-1;c=0;
            update(1,n,1);
        }
    }
    return 0;
}

这个是懒惰标记的代码

#include<stdio.h>
#define ls rt*2
#define rs rt*2+1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define canshu int l,int r,int rt
#define X 50010
int tr[X*4],lv[X*4],rv[X*4],sum[X*4];
void tclear(int rt,int s){
    sum[rt]=lv[rt]=rv[rt]=s;
}
void build(canshu){
    tr[rt]=-1;
    tclear(rt,r-l+1);
    if(l==r)return ;
    int mid=l+r>>1;
    build(lson);
    build(rson);
}
int max(int a,int b,int c){
    if(a>=b&&a>=c)return a;
    if(b>=a&&b>=c)return b;
    if(c>=a&&c>=b)return c;
}
void pushup(canshu){
    int mid=l+r>>1;
    lv[rt]=lv[ls]+(sum[ls]==mid-l+1?lv[rs]:0);
    rv[rt]=rv[rs]+(sum[rs]==r-mid?rv[ls]:0);
    sum[rt]=max(sum[ls],sum[rs],rv[ls]+lv[rs]);
}
void pushdown(canshu){
    if(tr[rt]!=-1){
        int mid=l+r>>1;
        tr[ls]=tr[rs]=tr[rt];
        tclear(ls,(!tr[rt])*(mid-l+1));
        tclear(rs,(!tr[rt])*(r-mid));
        tr[rt]=-1;
    }
}
int ll,rr,c;
void update(canshu){
    if(ll<=l&&rr>=r){
        tr[rt]=c;
        tclear(rt,(!c)*(r-l+1));
        return ;
    }
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(ll<=mid)update(lson);
    if(rr> mid)update(rson);
    pushup(l,r,rt);
}
int que(canshu){
    if(tr[rt]==0)return l;
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(sum[ls]>=c)return que(lson);
    if(rv[ls]+lv[rs]>=c)
        return mid-rv[ls]+1;
    return que(rson);
}
int main(){
    int f,pos,d,n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    while(m--){
        scanf("%d",&f);
        if(f==1){
            scanf("%d",&c);
            if(sum[1]<c){puts("0");continue;}
            pos=que(1,n,1);
            ll=pos;rr=pos+c-1;c=1;
            update(1,n,1);
            printf("%d\n",pos);
        }
        else {
            scanf("%d%d",&pos,&c);
            ll=pos;rr=pos+c-1;c=0;
            update(1,n,1);
        }
    }
    return 0;
}


你可能感兴趣的:(区间覆盖,懒惰标记)