【线段树】poj 3667 Hotel

来源:互联网 发布:htpc安装软件 编辑:程序博客网 时间:2024/05/17 22:21

这类题可当模板。询问最左边空闲的数,添加一段,删减一段。具体解释可看这里

struct tree{    int l,r,lv,rv,cv,state;}T[N];void init(int i){    T[i].lv=T[i].rv=T[i].cv=T[i].state==0?T[i].r-T[i].l+1:0;}void build(int l,int r,int i){    T[i].l=l,T[i].r=r;    T[i].state=0;            //空闲!    if(l==r){        T[i].lv=T[i].rv=T[i].cv=1;        return ;    }    int mid=(l+r)>>1;    build(l,mid,2*i);    build(mid+1,r,2*i+1);    T[i].lv=T[i].rv=T[i].cv=r-l+1;}void modify(int l,int r,int i,int d){    if(l<=T[i].l && r>=T[i].r){        T[i].state=d;        init(i);        return ;    }    if(T[i].state!=-1){        T[2*i].state=T[2*i+1].state=T[i].state;        init(2*i);        init(2*i+1);        T[i].state=-1;    //标记该区间不能用了!    }    int mid=(T[i].l+T[i].r)>>1;    if(r<=mid)        modify(l,r,2*i,d);    else if(l>=mid+1)        modify(l,r,2*i+1,d);    else {        modify(l,mid,2*i,d);        modify(mid+1,r,2*i+1,d);    }    T[i].lv=T[2*i].lv;     //注意:只有上面递归完才能更新父节点!    T[i].rv=T[2*i+1].rv;    T[i].cv=max(max(T[2*i].cv,T[2*i+1].cv),T[2*i].rv+T[2*i+1].lv);    if(T[i].lv==T[2*i].r-T[2*i].l+1)        T[i].lv+=T[2*i+1].lv;    if(T[i].rv==T[2*i+1].r-T[2*i+1].l+1)        T[i].rv+=T[2*i].rv;}int query(int x,int i){    if(T[i].l==T[i].r)        return T[i].l;    if(T[i].state!=-1){        T[2*i].state=T[2*i+1].state=T[i].state;        init(2*i);        init(2*i+1);        T[i].state=-1;    }    if(T[2*i].cv>=x)        return query(x,2*i);    else if(T[2*i].rv+T[2*i+1].lv>=x)        return T[2*i].r-T[2*i].rv+1;    else if(T[2*i+1].cv>=x)        return query(x,2*i+1);    return 0;}

POJ3667

#include <list>#include <map>#include <set>#include <queue>#include <string>#include <deque>#include <stack>#include <algorithm>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <limits.h>#include <time.h>#include <string.h>using namespace std;#define LL long long#define PI acos(-1.0)#define Max INT_MAX#define Min INT_MIN#define eps 1e-8#define FRE freopen("a.txt","r",stdin)#define N 150000struct tree{    int l,r,lv,rv,cv,state;}T[N];void init(int i){    T[i].lv=T[i].rv=T[i].cv=T[i].state==0?T[i].r-T[i].l+1:0;}void build(int l,int r,int i){    T[i].l=l,T[i].r=r;    T[i].state=0;            //空闲!    if(l==r){        T[i].lv=T[i].rv=T[i].cv=1;        return ;    }    int mid=(l+r)>>1;    build(l,mid,2*i);    build(mid+1,r,2*i+1);    T[i].lv=T[i].rv=T[i].cv=r-l+1;}void modify(int l,int r,int i,int d){    if(l<=T[i].l && r>=T[i].r){        T[i].state=d;        init(i);        return ;    }    if(T[i].state!=-1){        T[2*i].state=T[2*i+1].state=T[i].state;        init(2*i);        init(2*i+1);        T[i].state=-1;    //标记该区间不能用了!    }    int mid=(T[i].l+T[i].r)>>1;    if(r<=mid)        modify(l,r,2*i,d);    else if(l>=mid+1)        modify(l,r,2*i+1,d);    else {        modify(l,mid,2*i,d);        modify(mid+1,r,2*i+1,d);    }    T[i].lv=T[2*i].lv;     //注意:只有上面递归完才能更新父节点!    T[i].rv=T[2*i+1].rv;    T[i].cv=max(max(T[2*i].cv,T[2*i+1].cv),T[2*i].rv+T[2*i+1].lv);    if(T[i].lv==T[2*i].r-T[2*i].l+1)        T[i].lv+=T[2*i+1].lv;    if(T[i].rv==T[2*i+1].r-T[2*i+1].l+1)        T[i].rv+=T[2*i].rv;}int query(int x,int i){    if(T[i].l==T[i].r)        return T[i].l;    if(T[i].state!=-1){        T[2*i].state=T[2*i+1].state=T[i].state;        init(2*i);        init(2*i+1);        T[i].state=-1;    }    if(T[2*i].cv>=x)        return query(x,2*i);    else if(T[2*i].rv+T[2*i+1].lv>=x)        return T[2*i].r-T[2*i].rv+1;    else if(T[2*i+1].cv>=x)        return query(x,2*i+1);    return 0;}int main(){FRE;    int n,m;    while(scanf("%d%d",&n,&m)!=EOF){        int i,j;        build(1,n,1);        while(m--){            int a;            scanf("%d",&a);            if(a==1){                int x;                scanf("%d",&x);                int num=query(x,1);                printf("%d\n",num);                if(num){                    modify(num,num+x-1,1,1);                }            }            else{                int x,y;                scanf("%d%d",&x,&y);                modify(x,x+y-1,1,0);            }        }    }    return 0;}

原创粉丝点击