zoukankan      html  css  js  c++  java
  • 线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel

    题面:P2894 [USACO08FEB]酒店Hotel 

    题解:和基础的线段树操作差别不是很大,就是在传统的线段树基础上多维护一段区间最长的合法前驱(h_),最长合法后驱(t_),一段中最长的合法区间(mx)。询问时由于查询的是最左边的合法端点,所以要从左到中间到右边依次考虑情况。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define max(a,b) ((a)>(b)?(a):(b))
     5 using namespace std;
     6 const int maxn=50000+5,maxm=50000+5;
     7 int N,M,o,D,X,ans;
     8 inline int rd(){
     9     int x=0;char c=getchar();
    10     while(c<'0'||c>'9')c=getchar();
    11     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    12     return x;
    13 }
    14 struct Tree{
    15     int l,r,lazy,h_,t_,mx;
    16 }t[maxn<<2];
    17 inline void Pushup(int x){
    18     int ls=x<<1,rs=x<<1|1;
    19     if(t[ls].r-t[ls].l+1==t[ls].mx)t[x].h_=t[ls].mx+t[rs].h_;else t[x].h_=t[ls].h_;
    20     if(t[rs].r-t[rs].l+1==t[rs].mx)t[x].t_=t[rs].mx+t[ls].t_;else t[x].t_=t[rs].t_;
    21     t[x].mx=max(t[ls].mx,t[rs].mx);
    22     t[x].mx=max(t[x].mx,t[ls].t_+t[rs].h_);
    23     return;
    24 }
    25 inline void Build(int x,int l,int r){
    26     t[x].l=l;t[x].r=r;t[x].lazy=-1;
    27     if(l==r){
    28         t[x].h_=t[x].t_=t[x].mx=1;
    29         return;
    30     }
    31     int mid=(l+r)>>1;
    32     Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    33     Pushup(x);
    34     return;
    35 }
    36 inline void Pushdown(int x){
    37     if(t[x].lazy>=0){
    38         int k=t[x].lazy,ls=x<<1,rs=x<<1|1;t[x].lazy=-1;
    39         if(k==1){
    40             t[ls].h_=t[ls].t_=t[ls].mx=0;
    41             t[rs].h_=t[rs].t_=t[rs].mx=0;
    42         }
    43         else{
    44             t[ls].h_=t[ls].t_=t[ls].mx=t[ls].r-t[ls].l+1;
    45             t[rs].h_=t[rs].t_=t[rs].mx=t[rs].r-t[rs].l+1;
    46         }
    47         t[ls].lazy=t[rs].lazy=k;
    48     }
    49     return;
    50 }
    51 inline int Solve(int x,int d){
    52     int ls=x<<1,rs=x<<1|1,l=t[x].l,r=t[x].r;
    53     if(r-l+1==t[x].mx&&t[x].mx==d)return l;
    54     Pushdown(x);
    55     if(t[ls].mx>=d)return Solve(ls,d);
    56     if(t[ls].t_+t[rs].h_>=d)return (t[ls].r-t[ls].t_+1);
    57     if(t[rs].mx>=d)return Solve(rs,d);
    58     return 0;
    59 }
    60 inline void Update(int x,int ql,int qr,int o){
    61     int l=t[x].l,r=t[x].r;
    62     if(ql<=l&&r<=qr){
    63         if(o==1)t[x].h_=t[x].t_=t[x].mx=0;
    64         else t[x].h_=t[x].t_=t[x].mx=r-l+1;
    65         t[x].lazy=o;
    66         return;
    67     }
    68     int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
    69     Pushdown(x);
    70     if(ql<=mid)Update(ls,ql,qr,o);
    71     if(qr>mid)Update(rs,ql,qr,o);
    72     Pushup(x);
    73     return;
    74 }
    75 inline void write(int x){
    76     char a[12];int len=0;
    77     for(;x;x/=10)a[len++]=x%10;
    78     if(!len)putchar('0');
    79     else while(len)putchar(a[--len]+'0');
    80     putchar('
    ');
    81 }
    82 int main(){
    83     N=rd();M=rd();
    84     Build(1,1,N);
    85     while(M--){
    86         o=rd();
    87         if(o==1){
    88             D=rd();
    89             ans=Solve(1,D);
    90             write(ans);
    91             if(ans)Update(1,ans,ans+D-1,1);//1表示有住人 
    92         }
    93         else{
    94             X=rd();D=rd();
    95             Update(1,X,X+D-1,0);
    96         }
    97     }
    98     return 0;
    99 }

    //我为了卡常加入了快速读入和快速输出,实际食用代码时完全可以无视。


    By:AlenaNuna

  • 相关阅读:
    头部尾部始终处于两端(适用于pc端和移动端)
    运用active和hover实现导航栏的页面切换
    POJ1423-阶乘的位数-Big Number
    大数阶乘
    n皇后
    4103:踩方格
    2815:城堡问题
    特殊回文数
    十六进制转十进制
    十六进制转八进制
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10357986.html
Copyright © 2011-2022 走看看