zoukankan      html  css  js  c++  java
  • hdu 4614 Vases and Flowers (二分 线段树)

    题目大意:爱丽丝有N个花瓶,每个花瓶最多放一朵花。然后又如下两个操作。

    1:A B    从第A个花瓶开始,往后依次插B朵花,直到不能插为止。如果一朵花都不能插入就输出“can.....”,否则输出第一个插花位置和最后一个插花位置。

    2:A B    输出A B 之间有多少朵花   然后将这些花瓶清空。


    当时比赛的时候始终找不到办法求出 最后一个插花位置。  也想过二分  但是想着怕效率太慢就没写。

    其实最后想想也是 只有50000个操作   再乘以log N的二分  最多也就20W左右吧。   


    我是弱菜,自己写的程序效率巨慢。而且数组也开得多。


    思路:

    用lef 记录每个区间最左边可以放的花瓶,如果没有就是INF  

    用rig 记录每个区间最右边可以放的花瓶,如果没有就是-1

    以上两个在更新的时候  lef选较小的   rig选较大的

    cov表示区间全空 0 还是全满1  ,或者是不空不满  -1

    然后emp表示区间空花瓶数。

    主要的难点就是可以插花的时候怎么找到最后一个插花位置。

    那么就用二分  找那个 emp ==  所需要插花的数量 的最小右边的区间。

    详见代码。


    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <map>
    #include <set>
    #define maxn 50005
    #define lson num<<1,s,mid
    #define rson num<<1|1,mid+1,e
    #define INF 0x3f3f3f3f
    using namespace std;
    
    int emp[maxn<<2];
    int cov[maxn<<2];
    int lef[maxn<<2];
    int lzy[maxn<<2];
    int rig[maxn<<2];
    
    void pushup(int num)
    {
        emp[num]=emp[num<<1]+emp[num<<1|1];
    
        if(cov[num<<1]==0 && cov[num<<1|1]==0)cov[num]==0;
        else if(cov[num<<1|1]==1 && cov[num<<1]==1)cov[num]=1;
        else cov[num]=-1;
        lef[num]=min(lef[num<<1],lef[num<<1|1]);
        rig[num]=max(rig[num<<1|1],rig[num<<1]);
    }
    
    void pushdown(int num,int s,int e)
    {
        if(lzy[num]!=0)
        {
            int mid=(s+e)>>1;
    
            lzy[num<<1]=lzy[num<<1|1]=lzy[num];
    
            if(cov[num]!=-1)cov[num<<1]=cov[num<<1|1]=cov[num];
    
            if(cov[num<<1]==0)emp[num<<1]=mid-s+1;
            else if(cov[num<<1]==1)emp[num<<1]=0;
    
            if(cov[num<<1|1]==0)emp[num<<1|1]=e-mid;
            else if(cov[num<<1|1]==1)emp[num<<1|1]=0;
    
            if(cov[num]==0)
            {
                lef[num<<1]=s;
                rig[num<<1]=mid;
                lef[num<<1|1]=mid+1;
                rig[num<<1|1]=e;
            }
            else
            {
                lef[num<<1]=lef[num<<1|1]=INF;
                rig[num<<1]=rig[num<<1|1]=-1;
            }
            lzy[num]=0;
        }
    }
    
    void build(int num,int s,int e)
    {
        cov[num]=0;
        lef[num]=s;
        rig[num]=e;
        emp[num]=e-s+1;
        lzy[num]=0;
        if(s==e)return;
        int mid=(s+e)>>1;
    
        build(lson);
        build(rson);
        pushup(num);
    }
    
    void update(int num,int s,int e,int l,int r,int val)
    {
        if(l<=s && r>=e)
        {
            lzy[num]=1;
            cov[num]=val;
            emp[num]=val==0?e-s+1:0;
            lef[num]=val==0?s:INF;
            rig[num]=val==0?e:-1;
            return;
        }
        pushdown(num,s,e);
        int mid=(s+e)>>1;
        if(l<=mid)update(lson,l,r,val);
        if(r>mid)update(rson,l,r,val);
        pushup(num);
    }
    
    int query(int num,int s,int e,int l,int r)
    {
        //printf("emp=%d,s=%d,e=%d,l=%d,r=%d,cov=%d
    ",emp[num],s,e,l,r,cov[num]);
        if(l<=s && r>=e)
        {
            return emp[num];
        }
        pushdown(num,s,e);
        int mid=(s+e)>>1;
        if(r<=mid)return query(lson,l,r);
        else if(l>mid)return query(rson,l,r);
        else return query(lson,l,mid)+query(rson,mid+1,r);
        pushup(num);
    }
    
    int Q_L(int num,int s,int e,int l,int r)//找到区间的LEF 
    {
        if(l==s && r==e)
        {
            return lef[num];
        }
    
        pushdown(num,s,e);
        int mid=(s+e)>>1;
        if(r<=mid)return Q_L(lson,l,r);
        else if(l>mid)return Q_L(rson,l,r);
        else return min(Q_L(lson,l,mid),Q_L(rson,mid+1,r));
        pushup(num);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
    
            build(1,1,n);//额额额。  我是用1-N 建的树  而题目说的是 0-N-1  所以。。。后面有一些++操作。。。
            int tl,tr;
            while(m--)
            {
                int op,aa,bb;
                scanf("%d%d%d",&op,&aa,&bb);
    
                if(op==1)
                {
                    aa++;
                    int ll=Q_L(1,1,n,aa,n);//找到左边
                    if(ll==INF)
                    {
                        printf("Can not put any one.
    ");
                        continue;
                    }
                    printf("%d ",ll-1);
                    int ttmp=query(1,1,n,ll,n);
    
                    if(ttmp==0)
                    printf("Can not put any one.
    ");
                    else
                    {
                        if(ttmp<=bb)
                        {
                            printf("%d
    ",rig[1]-1);
                            update(1,1,n,ll,n,1);
                        }
                        else
                        {
                            int top=n,bot=ll,mid;
                            while(bot<=top)
                            {
                                mid=(bot+top)>>1;
                                int bin=query(1,1,n,ll,mid);
                                if(bin>bb)
                                top=mid-1;
                                else if(bin<bb)
                                bot=mid+1;
                                else break;
                            }
                            while(query(1,1,n,ll,mid)==bb)//找到最小的
                            {
                                mid--;
                                if(mid<=ll)break;
                            }
                            printf("%d
    ",mid+1-1);
                            update(1,1,n,ll,mid+1,1);
                        }
                    }
                }
                else
                {
                    aa++,bb++;
                    printf("%d
    ",bb-aa+1-query(1,1,n,aa,bb));
                    update(1,1,n,aa,bb,0);
                }
            }
            puts("");
        }
        return 0;
    }
    


  • 相关阅读:
    scanf使用尿性
    System : Assembly Programming
    Biology 03: Cardiovascular
    remove the smallest element from a linkedlist
    Relativity 04: CH4CH5
    Relativity 03: Space and Time in Classical Mechanics
    146 __str__和__repr__
    145 __init__和__new__
    144 __call__
    143 __doc__
  • 原文地址:https://www.cnblogs.com/pangblog/p/3285581.html
Copyright © 2011-2022 走看看