zoukankan      html  css  js  c++  java
  • POJ 3667 线段树区间合并裸题

    题意:给一个n和m,表示n个房间,m次操作,操作类型有2种,一种把求连续未租出的房间数有d个的最小的最左边的房间号,另一个操作时把从x到x+d-1的房间号收回。

    建立线段树,值为1表示未租出,0为租出,线段树实现区间合并,必须记录区间左右端点的状态,这样才能实现区间合并,用lsum记录以左端点开始的最长连续可租房间数,

    rsum记录右端点开始的最长连续可组房间数,msum记录该区间的最长连续可租房间数,那么,区间合并时,根节点的更新 msum = max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1]));

    另外还需lazy节点标记区间更新

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define N 50005
    using namespace std;
    int lsum[N<<2],rsum[N<<2],msum[N<<2],lazy[N<<2];
    void pushup(int l,int r,int rt)
    {
        int mid=(l+r)>>1;
        lsum[rt]=lsum[rt<<1];
        if(lsum[rt]==mid-l+1)lsum[rt]+=lsum[rt<<1|1];
        rsum[rt]=rsum[rt<<1|1];
        if(rsum[rt]==r-mid)rsum[rt]+=rsum[rt<<1];
        msum[rt]=max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1]));
    }
    void pushdown(int l,int r,int rt)
    {
        if(lazy[rt]!=-1)
        {
            int mid=(l+r)>>1;
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=lazy[rt]?mid-l+1:0;// lazy为1表示全部转为1,为0表示全部转为0
            msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=lazy[rt]?r-mid:0;
            lazy[rt]=-1;
        }
    }
    void build(int l,int r,int rt)
    {
        lazy[rt]=-1;
        lsum[rt]=rsum[rt]=msum[rt]=r-l+1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    }
    void update(int L,int R,int k,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            lazy[rt]=k;
            msum[rt]=lsum[rt]=rsum[rt]=k?r-l+1:0;
            return;
        }
        pushdown(l,r,rt);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,k,l,mid,rt<<1);
        if(R>mid)update(L,R,k,mid+1,r,rt<<1|1);
        pushup(l,r,rt);
    }
    int query(int len,int l,int r,int rt)
    {
        if(l==r)return l;
        pushdown(l,r,rt);
        int mid=(l+r)>>1;
        if(msum[rt<<1]>=len)return query(len,l,mid,rt<<1);
        else if(rsum[rt<<1]+lsum[rt<<1|1]>=len)return mid-rsum[rt<<1]+1;
        else return query(len,mid+1,r,rt<<1|1);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while (m--)
        {
            int k,x,d;
            scanf("%d",&k);
            if(k==1)
            {
                scanf("%d",&d);
                if(d>msum[1])printf("0\n");
                else
                {
                    int l=query(d,1,n,1);
                    printf("%d\n",l);
                    update(l,l+d-1,0,1,n,1);
                }
            }
            else
            {
                scanf("%d%d",&x,&d);
                update(x,x+d-1,1,1,n,1);
            }
        }
        return 0;
    }
  • 相关阅读:
    小程序的媒体组件
    微信小程序开发系列之Hello World
    centos 6 mysql 5.6 源码安装
    php 源码安装
    centos7 源码安装nginx
    CentOS 7.2部署MariaDB Galera Cluster(10.1.21-MariaDB) 3主集群环境
    MySQL读写分离
    MySQL主从复制(Master-Slave)实践
    lvs+keepalived+nginx负载均衡搭建
    Kubernetes在CentOS7下二进制文件方式安装、离线安装
  • 原文地址:https://www.cnblogs.com/xusirui/p/9455989.html
Copyright © 2011-2022 走看看