• Hotel POJ


    题意: 给定长度为n的区间 ,有2个操作:

    操作1: 在区间中靠左放k个元素,输出新放入元素中最左边的位置,如果放不下输出 0;

    操作2 : 清空 l 到 l+w-1这一段区间的元素

    这里有一个状态转移方程(即线段树的上推方式):

    线段树区间pos中储存  lcon--从区间左端L最大连续的区间长度 , rcon--从线段树右端R最大连续的区间长度 ,mcon 区间内最大的区间长度

    则:      t[pos].mcon = max{ t[Lpos].rcon+t[Rpos].lcon  ,t[Lpos].mcon  ,t[Rpos].mcon );

                 t[pos].lcon = t[Lpos].lcon+(t[Rpos],lcon);  t[pos].rcon = t[Rpos].rcon+(t[Lpos].rcon) (如果左或右区间整段连续,就加上括号里面的部分

    lazy标记的下移(对整段空或整段满的区间进行标记):

    void pushdown( int L ,int R, int pos){
        if( t[pos].tag!=0 && t[pos].tag!=1 ) return ;
        int Mid;
         t[posl].tag = t[posr].tag =t[pos].tag;
         t[posl].mcon = t[posl].lcon = t[posl].rcon = t[pos].tag ? mid - L+1 : 0 ;
         t[posr].mcon = t[posr].lcon = t[posr].rcon = t[pos].tag ? R-mid : 0 ;
         t[pos].tag = -1;
         return ;
    }

    查询:

    判断能否放下: 比较k与总区间最大连续区间长度t[ 1 ].mcon 的大小

    查询新放入元素最左坐标:如果左区间最大连续空区间大于目标长度就一直查询左区间,直到查询不了就判断左区间右连续加上右区间左连续可不可以,可以就输出结果,不行的话在查询右区间                                                                

    int query(  int L ,int R ,int pos ,int w ){
         if( L==R ) return L;
        // cout<< L <<' '<<R << ' '<<w<<endl;
         pushdown( L ,R ,pos);
         int Mid;
         if( t[posl].mcon >= w ) return query( lson , w);                                           //优先查左边
         else if( t[posl].rcon + t[posr].lcon >= w) return mid - t[posl].rcon +1 ; //查到左边放不下了,输出区间放在中间的结果
         else return query( rson ,w);                                                                            //中间放不了,最末查询右边
    }

    更新比较平常 ,就不说了

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define posl pos<<1
    #define posr pos<<1|1
    #define lson L ,mid ,posl
    #define rson mid+1 ,R ,posr
    #define Mid mid=(L+R)>>1
    
    struct tree{
         int lcon ,rcon ,mcon;
         int  tag;
    } t[50005<<2];
    void pushup( int L ,int R ,int pos){
         t[pos].lcon = t[posl].lcon;
         t[pos].rcon = t[posr].rcon;
         int Mid;
         if( t[pos].lcon == mid - L +1 ) t[pos].lcon += t[posr].lcon;
         if( t[pos].rcon == R - mid ) t[pos].rcon += t[posl].rcon;
         t[pos].mcon = max( t[posl].rcon+t[posr].lcon ,max( t[posl].mcon  ,t[posr].mcon));
    }
    
    void pushdown( int L ,int R, int pos){
        if( t[pos].tag!=0 && t[pos].tag!=1 ) return ;
        int Mid;
         t[posl].tag = t[posr].tag =t[pos].tag;
         t[posl].mcon = t[posl].lcon = t[posl].rcon = t[pos].tag ? mid - L+1 : 0 ;
         t[posr].mcon = t[posr].lcon = t[posr].rcon = t[pos].tag ? R-mid : 0 ;
         t[pos].tag = -1;
         return ;
    }
    
    void build( int L ,int R ,int pos){
         t[pos].tag = -1;
         t[pos].lcon = t[pos].rcon = t[pos].mcon = R - L +1;
         if( L == R) return ;
         int Mid;
         build( lson);
         build( rson);
    }
    
    void updata( int L ,int R ,int pos ,int l,int r,int v ){
         if( L>= l && R <= r ){
    
            t[pos].mcon = t[pos].rcon = t[pos].lcon = v ? R - L +1 : 0 ;
            t[pos].tag = v;
            return ;
         }
         if( L == R)return;
         pushdown( L ,R ,pos);
         int Mid;
         if( l <= mid ) updata( lson ,l ,r ,v);
         if( mid < r) updata( rson ,l ,r ,v);
         pushup( L ,R ,pos);
    }
    
    int query(  int L ,int R ,int pos ,int w ){
         if( L==R ) return L;
        // cout<< L <<' '<<R << ' '<<w<<endl;
         pushdown( L ,R ,pos);
         int Mid;
         if( t[posl].mcon >= w ) return query( lson , w);                                           //优先查左边
         else if( t[posl].rcon + t[posr].lcon >= w) return mid - t[posl].rcon +1 ; //查到左边放不下了,输出区间放在中间的结果
         else return query( rson ,w);                                                                            //中间放不了,最末查询右边
    }
    int main( ){
         int n,m;
         scanf( "%d%d" ,&n ,&m);
         build( 1 ,n ,1);
         while( m-- ){
             int op ,k ,l ,r;
             scanf("%d" ,&op);
             if( op ==1){
                 scanf("%d" ,&k);
                 if( t[1].mcon >=k){
                     l=query( 1 ,n ,1 ,k);
                     updata( 1 , n ,1 ,l ,l+k-1, 0);
                     printf("%d
    " ,l);
                 }
                 else printf("0
    ");
             }
             else{
                 scanf("%d%d",&l ,&r);
                 updata( 1 ,n ,1 ,l ,l+r-1,1);
             }
         }
         return 0;
    }
  • 相关阅读:
    (转)Javascript如何正确使用getElementById,getElementsByName() and getElementsByTagName()
    把一个json字符串转换成对应的c#类型
    (转)C#数字转固定长度的字符串
    WDBuyNET.DMSFrame.DMSLinq内部方法
    (Transfered)DOM最常用的方法和属性(Javascript DOM编程艺术,DOM Scripting)
    三星颁布发表供应多款Android手机全新晋级
    APNIC执委赵巍:IPv4向IPv6过渡再无退路
    谷歌Android操纵市廛下架染辣手机软件
    盗窟手机小我私人撤军华强北:市场一年不如一年
    华为“黑室”命系商务部防线
  • 原文地址:https://www.cnblogs.com/-ifrush/p/10632421.html
Copyright © 2020-2023  润新知