zoukankan      html  css  js  c++  java
  • 【线段树区间合并】POJ3667-Hotel

    【题意】

    一段区间初始均为可行。有两个操作:

    1→找出长度为w的一段可行区间,如果存在则返回这个可行区间最靠左的情况,并将该区间设为不可行;

    2→将区间[a,b]设为可行区间。

    【思路】

    经典的线段树合并,代码依旧用的是神犇的线段树模板。详见注释。

    【错误点】

    延迟标记的时候,忘记把cover清为-1了,导致RE!

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cstdlib>
      6 using namespace std;
      7 #define lson l,m,rt<<1
      8 #define rson m+1,r,rt<<1|1 
      9 const int MAXN=55555+10;
     10 int cover[MAXN<<2];//-1表示当前没有覆盖标记,1表示均覆盖为不可行,0表示均覆盖为可行 
     11 int lsum[MAXN<<2];//该区间从左起连续的可用区间长度的最大值 
     12 int msum[MAXN<<2];//该区间中连续的可用区间长度的最大值 
     13 int rsum[MAXN<<2];//该区间从右起连续的可用区间长度的最大值 
     14 
     15 void PushUp(int rt,int m)
     16 {
     17     lsum[rt]=lsum[rt<<1];
     18     if (lsum[rt]==m-(m>>1)) lsum[rt]+=lsum[rt<<1|1];
     19     /*如果左孩子全部为可用区间,那么加上右孩子的左端*/
     20     rsum[rt]=rsum[rt<<1|1];
     21     if (rsum[rt]==m>>1) rsum[rt]+=rsum[rt<<1];
     22     /*同上*/
     23     msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]) , rsum[rt<<1]+lsum[rt<<1|1]);
     24     /*该区间的可用区间可能是:左孩子最大的可用区间、有孩子最大的可用区间,和跨越左右孩子加在一起的可用区间*/
     25 }
     26 
     27 void PushDown(int rt,int m) 
     28 {
     29     if (cover[rt]!=-1)
     30     {
     31         cover[rt<<1]=cover[rt<<1|1]=cover[rt];
     32         if (cover[rt]==1)
     33         {
     34             msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=0;
     35             msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=0;
     36         }
     37         else
     38         {
     39             msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=m-(m>>1);
     40             msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=m>>1;
     41         }
     42         cover[rt]=-1;
     43         /*千万不要忘记将rt清为-1*/ 
     44     }
     45 }
     46 
     47 
     48 int query(int w,int l,int r,int rt)
     49 {
     50     if (l==r) return l;
     51     PushDown(rt,r-l+1);
     52     int m=(l+r)>>1;
     53     if (msum[rt<<1]>=w) return(query(w,lson));
     54     /*由于要找最左边的区间,按照左孩子、跨越两者、有孩子的顺序查找*/
     55     if (rsum[rt<<1]+lsum[rt<<1|1]>=w) return(m-rsum[rt<<1]+1);
     56     return(query(w,rson));
     57 }
     58 
     59 void update(int L,int R,int o,int l,int r,int rt)
     60 {
     61     if (L<=l && r<=R)
     62     {
     63         cover[rt]=o;
     64         if (o==1) msum[rt]=lsum[rt]=rsum[rt]=0;
     65             else msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
     66         return;
     67     }
     68     PushDown(rt,r-l+1);//这里是l和r,不要写成L和R 
     69     int m=(l+r)>>1;
     70     if (L<=m) update(L,R,o,lson); 
     71     if (m<R)  update(L,R,o,rson);
     72     PushUp(rt,r-l+1);
     73 }
     74 
     75 void build(int l,int r,int rt)
     76 {
     77     msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
     78     cover[rt]=-1;
     79     if (l==r) return;
     80     int m=(l+r)>>1;
     81     build(lson);
     82     build(rson);
     83 }
     84 
     85 int main()
     86 {
     87     int n,m;
     88     scanf("%d%d",&n,&m);
     89     build(1,n,1);
     90     for (int i=0;i<m;i++)
     91     {
     92         int op;
     93         scanf("%d",&op);
     94         if (op==1)
     95         {
     96             int w;
     97             scanf("%d",&w);
     98             if (msum[1]<w) cout<<0<<endl;
     99             /*如果根的可用区间已经小于w,那么一定是找不到长度为w的可用区间*/
    100                 else
    101                 {
    102                       int p=query(w,1,n,1);
    103                       cout<<p<<endl;
    104                       update(p,p+w-1,1,1,n,1);
    105                 }
    106         }
    107         else
    108         {
    109             int u,v;
    110             scanf("%d%d",&u,&v);
    111             update(u,u+v-1,0,1,n,1);
    112         }
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    一个页面从输入url到页面加载显示完成,中间都经历了什么
    获取鼠标点击的是那个键位、阻止鼠标点击的默认事件
    获取鼠标的位置
    图片上传
    jQuery实现瀑布流(pc、移动通用)
    怎么用js或jq点击展开,出现隐藏的DIV,点击收起DIV又隐藏起来.
    js商城倒计时
    页面跳转前动画加载,页面跳转后记住滚动位置
    乐观锁与悲观锁
    过滤器、监听器、拦截器的区别
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5172879.html
Copyright © 2011-2022 走看看