poj3667线段树

来源:互联网 发布:初学者怎么制作软件 编辑:程序博客网 时间:2024/05/23 15:01

题意:输入n,m;  n代表1-n的区间,m代表有m个操作。对于每个操作如果先输入1,则输入w,找到区间最左边未被占用的连续长度为w的区间,返回左端点,并把这段区间标记为已被占用。如果整个区间没有找到符合条件的区间。则返回0。如果输入为2,则将这段区间标记为未被占用。

解法:维护3个变量sum,lsum,rsum,sum代表的是这段区间最大连续区间的长度。lsum是从这个区间第一个元素开始连续未被占用的区间的长度,rsum是当前区间最右端开始连续未被占用的区间长度。对于每次查询,如果sum<w直接返回0。从第一段区间开始如果他的左儿子的最大连续未被占用区间的长度大于w,则查询左子树。否则如果左儿子的rsum+右儿子的lsum>=w,则返回左子树从右往左最后一个未被用占用的点。否则查询右子树。查询完后更新,更新的时候如果cover标记为1则覆盖,cover标记为0则清空。注意写法。

#include <iostream>#include <cstdio>#include <algorithm>#define N 100005using namespace std;struct node{    int l,r,lz;    int sum,lsum,rsum;    int cover;  //cover=-1没有标记 cover=0清零操作 cover=1覆盖操作}a[N<<2];void pushdown(int k){    int m=a[k].r-a[k].l+1;    if(a[k].cover!=-1){        a[k<<1].cover=a[k].cover;        a[k<<1|1].cover=a[k].cover;        if(a[k].cover==0){            a[k<<1].lsum=a[k<<1].rsum=a[k<<1].sum=m-(m>>1);            a[k<<1|1].lsum=a[k<<1|1].rsum=a[k<<1|1].sum=m>>1;        }        else{            a[k<<1].lsum=a[k<<1].rsum=a[k<<1].sum=0;            a[k<<1|1].lsum=a[k<<1|1].rsum=a[k<<1|1].sum=0;        }        a[k].cover=-1;    }}void pushup(int k){    int m=a[k].r-a[k].l+1;    a[k].lsum=a[k<<1].lsum;    a[k].rsum=a[k<<1|1].rsum;    if(a[k].lsum==m-(m>>1))        a[k].lsum+=a[k<<1|1].lsum;    if(a[k].rsum==(m>>1))        a[k].rsum+=a[k<<1].rsum;    a[k].sum=max(a[k<<1|1].lsum+a[k<<1].rsum,max(a[k<<1].sum,a[k<<1|1].sum));}void build(int l,int r,int k){    a[k].l=l,a[k].r=r,a[k].sum=a[k].lsum=a[k].rsum=(r-l+1);    a[k].cover=-1;    if(l==r){        return ;    }    else{        int mid=(l+r)>>1;        build(l,mid,k<<1);        build(mid+1,r,k<<1|1);    }}int query(int l,int r,int w,int k){    if(l==r){        return l;    }    else{        pushdown(k);        int mid=(l+r)>>1;        if(a[k<<1].sum>=w){            return query(l,mid,w,k<<1);        }        else if(a[k<<1].rsum+a[k<<1|1].lsum>=w){            return mid-a[k<<1].rsum+1;        }        else{            return query(mid+1,r,w,k<<1|1);        }    }}void update(int l,int r,int co,int k){    if(a[k].l==l && a[k].r==r){        a[k].cover=co;        if(co){            a[k].sum=a[k].lsum=a[k].rsum=0;        }        else{            a[k].sum=a[k].lsum=a[k].rsum=a[k].r-a[k].l+1;        }        return ;    }    else{        pushdown(k);        int mid=(a[k].l+a[k].r)>>1;        if(mid>=r){            update(l,r,co,k<<1);        }        else if(mid<l){            update(l,r,co,k<<1|1);        }        else{            update(l,mid,co,k<<1);            update(mid+1,r,co,k<<1|1);        }        pushup(k);    }}int main(){    int n,m;    while(~scanf("%d%d",&n,&m)){        build(1,n,1);        while(m--){            int cao;            scanf("%d",&cao);            if(cao==1){                int w;                scanf("%d",&w);                if(a[1].sum<w){                    printf("0\n");                }                else{                    int ans=query(1,n,w,1);                    printf("%d\n",ans);                    update(ans,ans+w-1,1,1);                    //cout<<1<<endl;                }            }            else{                int x,y;                scanf("%d%d",&x,&y);                update(x,x+y-1,0,1);            }       }    }    return 0;}


 

 

0 0
原创粉丝点击