【bzoj1593-预定旅馆】线段树维护连续区间

题解:

这题非常经典啊似乎。。经典模型要记住啊。。

对于每个节点维护该区间里的最大的连续区间,然后我们就可以logn递归找最前面的一段。

那就维护mx(无限制),lmx(必须从左边开始),rmx(必须从右边开始)。

代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<ctime>
  6 #include<queue>
  7 #include<algorithm>
  8 using namespace std;
  9 
 10 const int N=50010;
 11 int n,m,tl;
 12 struct trnode{
 13     int l,r,lc,rc,mx,lmx,rmx,len,lazy;
 14 }t[2*N];
 15 
 16 int minn(int x,int y){return x<y ? x:y;}
 17 int maxx(int x,int y){return x>y ? x:y;}
 18 
 19 int bt(int l,int r)
 20 {
 21     int x=++tl;
 22     t[x].l=l;t[x].r=r;
 23     t[x].lc=t[x].rc=0;
 24     t[x].lazy=-1;t[x].len=r-l+1;
 25     t[x].lmx=t[x].rmx=t[x].mx=t[x].len;
 26     if(l<r)
 27     {
 28         int mid=(l+r)/2;
 29         t[x].lc=bt(l,mid);
 30         t[x].rc=bt(mid+1,r);
 31     }
 32     return x;
 33 }
 34 
 35 void pd(int x)
 36 {
 37     if(t[x].lazy==-1) return ;
 38     int d=t[x].lazy,lc=t[x].lc,rc=t[x].rc,l=t[x].l,r=t[x].r;
 39     t[x].lazy=-1;
 40     if(d==0) t[x].mx=t[x].lmx=t[x].rmx=t[x].len;
 41     else t[x].mx=t[x].lmx=t[x].rmx=0;
 42     if(lc) t[lc].lazy=d;
 43     if(rc) t[rc].lazy=d;
 44 }
 45 
 46 void upd(int x)
 47 {
 48     int lc=t[x].lc,rc=t[x].rc;
 49     pd(x);pd(lc);pd(rc);
 50     t[x].lmx=t[lc].lmx;
 51     if(t[lc].lmx==t[lc].len) t[x].lmx+=t[rc].lmx;
 52     t[x].rmx=t[rc].rmx;
 53     if(t[rc].rmx==t[rc].len) t[x].rmx+=t[lc].rmx;
 54     t[x].mx=maxx(maxx(maxx(t[x].lmx,t[x].rmx),t[lc].rmx+t[rc].lmx),maxx(t[lc].mx,t[rc].mx));//debug 一开始这里忘了取lc和rc的mx了。
 55 }
 56 
 57 void change(int x,int l,int r,int d)
 58 {
 59     pd(x);
 60     if(t[x].l==l && t[x].r==r) {t[x].lazy=d;pd(x);return ;}
 61     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)/2;
 62     if(r<=mid) change(lc,l,r,d);
 63     else if(l>mid) change(rc,l,r,d);
 64     else 
 65     {
 66         change(lc,l,mid,d);
 67         change(rc,mid+1,r,d);
 68     }
 69     upd(x);
 70 }
 71 
 72 int query(int x,int len)
 73 {
 74     pd(x);
 75     int k,lc=t[x].lc,rc=t[x].rc;
 76     if(t[x].mx>=len)
 77     {
 78         if(t[x].lmx>=len) return t[x].l;
 79         if((k=query(lc,len)) > 0) return k;
 80         if(t[lc].rmx+t[rc].lmx>=len) return t[lc].r-t[lc].rmx+1;
 81         if((k=query(rc,len)) > 0) return k;
 82     }
 83     return 0;
 84 }
 85 
 86 int main()
 87 {
 88     // freopen("a.in","r",stdin);
 89     freopen("hotel.in","r",stdin);
 90     freopen("hotel.out","w",stdout);
 91     scanf("%d%d",&n,&m);
 92     tl=0;
 93     bt(1,n);
 94     for(int i=1;i<=m;i++)
 95     {
 96         int tmp,x,len;
 97         scanf("%d",&tmp);
 98         if(tmp==1)
 99         {
100             scanf("%d",&len);
101             x=query(1,len);
102             printf("%d\n",x);
103             if(x>0) change(1,x,x+len-1,1);
104         }
105         else 
106         {
107             scanf("%d%d",&x,&len);
108             change(1,x,x+len-1,0);
109         }
110     }
111     return 0;
112 }

 

posted @ 2016-11-01 15:05  拦路雨偏似雪花  阅读(356)  评论(0编辑  收藏  举报