poj3667

来源:互联网 发布:模糊逻辑算法 编辑:程序博客网 时间:2024/05/24 03:09

链接:点击打开链接

题意:有N个连续的空房间,分别编号1~N,M条指令,指令分为两种,分别为1 D和2 X D,第一种指令输出是否有D个连续的空房间,如果有则输出最靠左的第一个房间编号,否则则输出0,第二种则将从X开始D个房间清空

代码:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>using namespace std;const int SIZE=50005;int sum[SIZE<<2],lsum[SIZE<<2],rsum[SIZE<<2];           //sum表示当前节点所代表的区间最长连续空位int add[SIZE<<2];                                       //lsum表示当前节点所代表的区间从左端起的最长连续空位void pushdown(int rt,int m){                            //rsum表示当前节点所代表的区间从右端起的最长连续空位    if(add[rt]!=-1){        add[rt<<1]=add[rt<<1|1]=add[rt];        sum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=add[rt]?0:(m-(m>>1));        sum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=add[rt]?0:(m>>1);        add[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];    sum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1],max(sum[rt<<1],sum[rt<<1|1]));}                                                       //根据lsum和rsum判断sumvoid build(int l,int r,int rt){    int m;    sum[rt]=lsum[rt]=rsum[rt]=r-l+1;    add[rt]=-1;    if(l==r)    return;    m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);}void update(int L,int R,int c,int l,int r,int rt){    int m;    if(L<=l&&r<=R){        sum[rt]=lsum[rt]=rsum[rt]=c?0:r-l+1;        add[rt]=c;        return;    }    pushdown(rt,r-l+1);    m=(l+r)>>1;    if(L<=m)    update(L,R,c,l,m,rt<<1);    if(R>m)    update(L,R,c,m+1,r,rt<<1|1);    pushup(rt,r-l+1);}                                                       //建树和更新和成段更新也几乎是一样的int query(int w,int l,int r,int rt){    int m;    if(l==r)    return l;    pushdown(rt,r-l+1);    m=(r+l)>>1;    if(sum[rt<<1]>=w)                                   //因为题目要求尽可能靠左,因此先查询左区间    return query(w,l,m,rt<<1);    else if(lsum[rt<<1|1]+rsum[rt<<1]>=w)               //然后左右区间相连    return m-rsum[rt<<1]+1;    return query(w,m+1,r,rt<<1|1);                      //最后查询右区间}                                                           int main(){    int n,m,i,j,a,b,c,tmp;    while(scanf("%d%d",&n,&m)!=EOF){        build(1,n,1);        while(m--){            scanf("%d",&c);            if(c==1){                scanf("%d",&a);                if(sum[1]<a){                    puts("0");                    continue;                }                                       //没有时输出0                    tmp=query(a,1,n,1);                printf("%d\n",tmp);                update(tmp,tmp+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