zoukankan      html  css  js  c++  java
  • 【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
    ",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 }
  • 相关阅读:
    第六周学习进度总结
    构建之法阅读笔记03
    文件操作
    数组相关
    compareTo
    我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 比如n=3时,2*3的矩形块有3种覆盖方法:
    从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行
    整数中1出现的次数
    Java泛型(看着好有用)
    输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/6019493.html
Copyright © 2011-2022 走看看