POJ

来源:互联网 发布:联赢软件 编辑:程序博客网 时间:2024/06/03 14:36

点我看题

题意:有L个连续的房间,日常会有一些人登记入住,也会有一些人退房,一次登记入住和一次退房都是连续的,问每次登记入住时,是否有连续的房间提供给入住者们,有的话,求入住的第一个房间序号.

分析:裸的线段树区间合并加查询,入住的时候,查询是否有满足条件的房间(st[1].sum>=所需要的房间数就是满足条件了),然后更新线段树,退房的话就更简单了,直接更新结点的长度就好.

参考代码:

/*区间合并*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define lson rt<<1#define rson rt<<1|1const int maxn = 5e4+10;int n,q;struct SegTree{        int l,r;        int sum;//当前结点保存的可入住人数的值        int lsum,rsum;//当前结点        int tag;//tag=1代表入住,-1代表退房,0代表不进行操作};SegTree st[maxn<<2];//向上更新void PushUp( int rt){    st[rt].lsum = st[lson].lsum;    st[rt].rsum = st[rson].rsum;    int mid = (st[rt].l+st[rt].r)>>1;    if( st[rt].lsum == mid-st[rt].l+1)        st[rt].lsum += st[rson].lsum;    if( st[rt].rsum == st[rt].r-mid)        st[rt].rsum += st[lson].rsum;    st[rt].sum = max(max(st[lson].sum,st[rson].sum),st[lson].rsum+st[rson].lsum);}//建树void Build( int l, int r, int rt){    st[rt].l = l;    st[rt].r = r;    st[rt].sum = r-l+1;    st[rt].lsum = r-l+1;    st[rt].rsum = r-l+1;    st[rt].tag = 0;    if( l == r)        return;    int mid = (l+r)>>1;    Build(l,mid,lson);    Build(mid+1,r,rson);//    PushUp(rt);//这里不需要往上更新}//向下更新void PushDown( int rt){    if( st[rt].tag != 0)    {        st[lson].tag = st[rson].tag = st[rt].tag;        if( st[rt].tag == 1)        {            st[lson].sum = st[lson].lsum = st[lson].rsum = 0;            st[rson].sum = st[rson].lsum = st[rson].rsum = 0;        }        else if( st[rt].tag == -1)        {            st[lson].sum = st[lson].lsum = st[lson].rsum = st[lson].r-st[lson].l+1;            st[rson].sum = st[rson].lsum = st[rson].rsum = st[rson].r-st[rson].l+1;        }        st[rt].tag = 0;    }}//区间查询//查询有没有区间长度至少为len的区间//个人认为这里的l和r都可以通过rt得到,但是为了书写方便,还是给加上去了int Query( int l, int r, int rt, int len){    if( l == r)        return l;    PushDown(rt);//继续向下更新查找    int mid = (l+r)>>1;    if( st[lson].sum >= len)        return Query(l,mid,lson,len);    else if( st[lson].rsum+st[rson].lsum >= len)        return mid-st[lson].rsum+1;    else        return Query(mid+1,r,rson,len);}//区间合并void Update( int L, int R, int rt, int tag){    if( st[rt].l == L && st[rt].r == R)    {        st[rt].tag = tag;        if( tag == 1)            st[rt].sum = st[rt].lsum = st[rt].rsum = 0;        else if( tag == -1)            st[rt].sum = st[rt].lsum = st[rt].rsum = st[rt].r-st[rt].l+1;        return;    }    PushDown(rt);//向下更新    int mid = (st[rt].l+st[rt].r)>>1;    if( R <= mid)        Update(L,R,lson,tag);    else if( L > mid)        Update(L,R,rson,tag);    else    {        Update(L,mid,lson,tag);        Update(mid+1,R,rson,tag);    }    PushUp(rt);//向上更新}int main(){    while( ~scanf("%d%d",&n,&q))    {        Build(1,n,1);        while( q--)        {            int op;            int x,y;            scanf("%d",&op);            if( op == 1)            {                scanf("%d",&x);                if( x <= st[1].sum)                {                        int pos = Query(1,n,1,x);                        printf("%d\n",pos);                        //pos和pos+x-1分别表示更新的起始和结束的位置                        //第一个1为根结点,第二个1为tag标记                        Update(pos,pos+x-1,1,1);                }                else                    puts("0");            }            else if( op == 2)            {                scanf("%d%d",&x,&y);                //参数意义同上                Update(x,x+y-1,1,-1);            }        }    }    return 0;}


原创粉丝点击