POJ 3667 線段樹 + 延遲標記 + 區間處理

來源:互聯網
上載者:User
/*貼個神牛的代碼,自己寫的代碼難看的別提有多噁心了 ...類型:線段樹 + 延遲標記 + 區間合并... */#include<iostream>#include<cstring>#include<cctype>#include<cstdio>#include<algorithm>using namespace std;#define L(r) r<<1#define R(r) r<<1|1const int MAXM=50005;typedef struct{    int lsum,rsum,msum;//分別表示左邊最大房間數,右邊最大房間數,整體最大房間數    int cover;//是否住下}node;node tree[MAXM<<2];void pushDown(int root,int m)//向下更新{    if(tree[root].cover==-1) return;//是否已經更新    tree[L(root)].cover=tree[R(root)].cover=tree[root].cover;    tree[L(root)].msum=tree[L(root)].lsum=tree[L(root)].rsum=tree[root].cover?0:m-(m>>1);    tree[R(root)].msum=tree[R(root)].lsum=tree[R(root)].rsum=tree[root].cover?0:(m>>1);    tree[root].cover=-1;}void pushUp(int root,int m)//向上更新{    tree[root].lsum=tree[L(root)].lsum;    tree[root].rsum=tree[R(root)].rsum;    if(tree[root].lsum==m-(m>>1) ) tree[root].lsum+=tree[R(root)].lsum;  // 區間合并     if(tree[root].rsum==(m>>1) ) tree[root].rsum+=tree[L(root)].rsum;       tree[root].msum=max(tree[R(root)].lsum+tree[L(root)].rsum,max(tree[L(root)].msum,tree[R(root)].msum) );}void Create(int l,int r,int root)//建樹過程{    tree[root].cover=-1;    tree[root].lsum=tree[root].rsum=tree[root].msum=r-l+1;    if(l==r){return;}    int mid=(l+r)>>1;    Create(l,mid,L(root));    Create(mid+1,r,R(root));}void update(int ll,int rr,int c,int l,int r,int root)//更新{    if(ll<=l&&r<=rr)//如果找到這個範圍就直接賦值返回,不向下繼續更新    {        tree[root].msum=tree[root].lsum=tree[root].rsum=c?0:r-l+1;        tree[root].cover=c;        return;    }    pushDown(root,r-l+1);//用到這個節點的子節點的時候就向下更新    int m=(l+r)>>1;    if(ll<=m) update(ll,rr,c,l,m,L(root));    if(m<rr) update(ll,rr,c,m+1,r,R(root));    pushUp(root,r-l+1);//向下更新完後需要把節點資訊反饋給父節點}int query(int w,int l,int r,int root)//查詢滿足連續房間數量的最左節點{    if(l==r) return l;    pushDown(root,r-l+1 );//用到這個節點的子節點的時候就向下更新    int m=(l+r)>>1;    //////////////////// 注意順序, 區間的處理     if(tree[L(root)].msum>=w) return query(w,l,m,L(root));//如果左兒子滿足就詢問左兒子    else if(tree[L(root)].rsum+tree[R(root)].lsum>=w) return m-tree[L(root)].rsum+1;//如果左兒子和右兒子之間的數量滿足,則範圍左兒子右邊連續房間第一個的編號    else return query(w,m+1,r,R(root));//如果兩者都不滿足則詢問右兒子}int main(){    int n,m;    while(~scanf("%d %d",&n,&m))    {        Create(1,n,1);        int a,num,x,d,p;        for(int i=0;i<m;++i)        {            scanf("%d",&a);            if(1==a)            {                scanf("%d",&num);                if(tree[1].msum<num) puts("0");//如果整個區間的最大連續房間數量小於預定的數量就輸出0                else                {                    p=query(num,1,n,1);//找到最左節點p                    printf("%d\n",p);                    update(p,p+num-1,1,1,n,1);//把已經有人的房間標記一下                }            }            else            {                scanf("%d %d",&x,&d);                update(x,x+d-1,0,1,n,1);//把此範圍的房間標記成無人            }        }    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.