zoukankan      html  css  js  c++  java
  • 【转】poj 1823 hotel 线段树【Good】

    题意:一个hotel,有n个连续的房间,开始时均无人住宿

    共有3种操作

    1 a b 从a开始连续b个房间全部旅客住宿 [a,a+b-1];

    2 a b 从a开始连续b个房间全部旅客离开 [a,a+b-1];

    3 查询最长连续空房间

    思路:线段树,记录每个节点,左边,右边各最多连续空房间lmax,rmax; 以及这个区间内最多空房间max

    #include<iostream>
     #include<cmath>
     using namespace std;
     #define MAXN 16001
     struct node
     {
         int lmax,rmax,max;
         int left,right;
         int flag;//0:全空;1:全部被占用;2:部分被占用
     };
     node tree[MAXN*4];
     void build(int i)
     {
         tree[i].lmax=tree[i].rmax=tree[i].max=tree[i].right-tree[i].left+1;//当前节点的max,lmax和rmax都初始化为right-left+1
         tree[i].flag=0;
         if(tree[i].left==tree[i].right) return ;
         int mid=(tree[i].left+tree[i].right)/2;
         tree[2*i].left=tree[i].left; tree[2*i].right=mid;
         tree[2*i+1].left=mid+1; tree[2*i+1].right=tree[i].right;
         build(2*i); build(2*i+1);
     }
     
     void insert(int i,int x,int y,int c)
     {
         //cout<<i<<" "<<x<<" "<<y<<" "<<c<<" "<<tree[i].left<<" "<<tree[i].right<<endl;
         if(tree[i].left==x&&tree[i].right==y)
         {
             tree[i].flag=c;
             if(c==1) tree[i].lmax=tree[i].rmax=tree[i].max=0;
             else tree[i].lmax=tree[i].rmax=tree[i].max=tree[i].right-tree[i].left+1;
             return;
         }

       //当前节点完全递归返回前未被占用,保证“当前节点的子节点的状态被标记为0”优先级最高

       //具体解析:因为之前操作中的插入或者删除操作都是到达满足if(tree[i].left==x&&tree[i].right==y)的条件之后就返回了,

       //但是我们之后要进行的插入和删除操作要是区段有可能比之前涉及到的区段小,这个时候在递归之前判断当前节点状态并且

       //对相应左子树和右子树执行更新操作就很有必要了
         if(tree[i].flag==0)
         {
             tree[2*i].flag=tree[2*i+1].flag=0;

       //左右子树的各个最长子段都设为right-left+1
             tree[2*i].lmax=tree[2*i].rmax=tree[2*i].max=tree[2*i].right-tree[2*i].left+1;
             tree[2*i+1].lmax=tree[2*i+1].rmax=tree[2*i+1].max=tree[2*i+1].right-tree[2*i+1].left+1;
         }

       //当前节点递归返回前完全被占用,保证“当前节点的子节点的状态被标记为1”优先级最高(具体解析同上)
         if(tree[i].flag==1)
         {  
             tree[2*i].flag=tree[2*i+1].flag=1;
       //左右子树的各个最长子段都设为0
             tree[2*i].lmax=tree[2*i].rmax=tree[2*i].max=0;
             tree[2*i+1].lmax=tree[2*i+1].rmax=tree[2*i+1].max=0;
         }
      //递归操作
         int mid=(tree[i].left+tree[i].right)/2;
         if(y<=mid) insert(2*i,x,y,c);
         else if(x>mid) insert(2*i+1,x,y,c);
         else
         {
             insert(2*i,x,mid,c);
             insert(2*i+1,mid+1,y,c);
         }
      //延迟处理,更新当前节点的状态
         if(tree[2*i].flag==0&&tree[2*i+1].flag==0)//左右子树均全空
         {
             tree[i].flag=0;
             tree[i].lmax=tree[i].rmax=tree[i].max=tree[i].right-tree[i].left+1;
         }
         else if(tree[2*i].flag==0&&tree[2*i+1].flag==1)//左子树全空,右子树全被占用
         {
             tree[i].flag=2;
             tree[i].lmax=tree[i].max=tree[2*i].max;
             tree[i].rmax=0;
         }
         else if(tree[2*i].flag==1&&tree[2*i+1].flag==0)//左子树被占用,右子树全空
         {
             tree[i].flag=2;
             tree[i].rmax=tree[i].max=tree[2*i+1].max;
             tree[i].lmax=0;
         }
         else if(tree[2*i].flag==1&&tree[2*i+1].flag==1)//左右子树都全被占用
         {
             tree[i].flag=1;       
             tree[i].lmax=tree[i].rmax=tree[i].max=0;  
         }
         else//左子树或者右子树含有部分被占用的情况
         {
             tree[i].flag=2;
             tree[i].max=max(tree[2*i].max,tree[2*i+1].max);
             tree[i].max=max(tree[i].max,tree[2*i].rmax+tree[2*i+1].lmax);
             if(tree[2*i].flag==0)

                     tree[i].lmax=tree[2*i].max+tree[2*i+1].lmax;
             else

                      tree[i].lmax=tree[2*i].lmax;
             if(tree[2*i+1].flag==0)

          tree[i].rmax=tree[2*i].rmax+tree[2*i+1].max;
             else

                     tree[i].rmax=tree[2*i+1].rmax;
         }
     } 
     int main()
     {
         int n,m;
         scanf("%d%d",&n,&m);
         tree[1].left=1; tree[1].right=n;
         build(1);
         int i;
         int x,y,c;
         for(i=1;i<=m;i++)
         {
             scanf("%d",&c);
             if(c==3) printf("%d\n",tree[1].max);
             if(c==1)
             {
                 scanf("%d%d",&x,&y);
                 insert(1,x,x+y-1,1);
             }
             if(c==2)
             {
                 scanf("%d%d",&x,&y);
                 insert(1,x,x+y-1,0);
             }
         }
         return 0;
     }

  • 相关阅读:
    leetcode刷题四<寻找两个有序数组的中位数>
    leetcode刷题第三天<无重复字符的最长子串>
    leetcode刷题第二天<两数相加>
    leetcode刷题第一日<两数和问题>
    sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError)
    flask微电影系统开发中上下文处理器
    gdb解决字符串打印果断措施
    邻接表
    Jarvis OJ 一些简单的re刷题记录和脚本
    windows控件理论学习
  • 原文地址:https://www.cnblogs.com/lzhitian/p/2612647.html
Copyright © 2011-2022 走看看