zoukankan      html  css  js  c++  java
  • POJ2667 Hotel(线段树区间合并)

    这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并

    题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
    2 a b:将[a,a+b-1]的房间清空
    思路:记录区间中最长的空房间
    线段树操作:update:区间替换 query:询问满足条件的最左断点

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define M 50005
    #define ls node<<1,l,m
    #define rs node<<1|1,m+1,r
    int n,m,ltree[M<<2],rtree[M<<2],mtree[M<<2],cover[M<<2];
    void pushdown(int node,int m)
    {
        if(cover[node]!=-1)
        {
            cover[node<<1]=cover[node<<1|1]=cover[node];
            mtree[node<<1]=ltree[node<<1]=rtree[node<<1]=cover[node]?0:m-(m>>1);
            mtree[node<<1|1]=ltree[node<<1|1]=rtree[node<<1|1]=cover[node]?0:(m>>1);
            cover[node]=-1;
        }
    }
    void pushup(int node,int m)
    {
        ltree[node]=ltree[node<<1];
        rtree[node]=rtree[node<<1|1];
        if(ltree[node]==m-(m>>1)) ltree[node]+=ltree[node<<1|1];
        if(rtree[node]==(m>>1)) rtree[node]+=rtree[node<<1];
        mtree[node]=max(ltree[node<<1|1]+rtree[node<<1],max(mtree[node<<1],mtree[node<<1|1]));
    }
    void buildtree(int node,int l,int r)
    {
        mtree[node]=ltree[node]=rtree[node]=r-l+1;
        cover[node]=-1;
        if(l==r) return ;
        int m=(l+r)>>1;
        buildtree(ls);
        buildtree(rs);
    }
    void update(int L,int R,int c,int node,int l,int r)
    {
        if(L<=l&&r<=R)
        {
            mtree[node]=ltree[node]=rtree[node]=c?0:r-l+1;
            cover[node]=c;
            return ;
        }
        pushdown(node,r-l+1);
        int m=(l+r)>>1;
        if(L<=m) update(L,R,c,ls);
        if(m<R) update(L,R,c,rs);
        pushup(node,r-l+1);
    }
    int query(int node,int l,int r,int w)
    {
        if(l==r) return l;
        pushdown(node,r-l+1);
        int m=(l+r)>>1;
        if(mtree[node<<1]>=w) return query(ls,w);
        else if(rtree[node<<1]+ltree[node<<1|1]>=w) return (m-rtree[node<<1]+1);
        return query(rs,w);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        buildtree(1,1,n);
        while(m--)
        {
            int op,a,b;
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d",&a);
                if(mtree[1]<a) printf("0
    ");
                else
                {
                    int p=query(1,1,n,a);
                    printf("%d
    ",p);
                    update(p,p+a-1,1,1,1,n);
                }
            }
            else
            {
                scanf("%d%d",&a,&b);
                update(a,a+b-1,0,1,1,n);
            }
        }
        return 0;
    }
  • 相关阅读:
    linux开关机命令
    实现vmare虚拟机系统随主机开机自动启动
    linux常用命令
    centos7.3上用源代码安装zabbix3.2.7
    centos7用yum搭建LAMP环境
    centos7永久更改主机名
    Python基础学习-列表的常用方法
    中兴交换机配置命令
    dml并行
    11.2.0.4 aix下运行第二个节点root.sh报错处理
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/4750003.html
Copyright © 2011-2022 走看看