ACWing 261 旅馆(Hotel)

Posted luyiming的小屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACWing 261 旅馆(Hotel)相关的知识,希望对你有一定的参考价值。

Problem(Description)

现在有一个长度为\\(n\\)的序列和\\(m\\)个操作,操作有两种:

  • \\(1,d\\) 寻找到最左边的连续\\(d\\)\\(0\\)的序列,并全部变成\\(1\\)
  • \\(2,x,d\\)\\([x,x + d - 1]\\)块全部变成\\(0\\)
    \\(1 \\le n,m \\le 50000\\)

Solution

Thinking 1

其实这个题就两个东西:

  1. 找到最左边的长度不小于\\(d\\)的最长\\(0\\)
  2. 区间修改
    显然2可以用线段树做,1怎么做呢?

Thinking 2

想到洛谷 P4513 小白逛公园这一题,通过维护左边最长段,右边最长段和总最长段来确定,那么连续\\(0\\)块是不是也能这么做?

Thinking 3

\\(T[root].lmax\\)为当前左边最长段,\\(T[root].rmax\\)同理,\\(T[root].Max\\)为总最长段。
在update时,如果是被完全包含的情况,若是add,那么三者全部变为0,否则全部变为这个节点的长度。
在pushdown的时候基本差不多,具体看代码。
pushup就是分别考虑更新当前节点的lmax,rmax和Max:
lmax:若左节点全部是0,那么lmax = l.Max + r.lmax; 否则lmax = l.lmax;
rmax:若右节点全部是0,那么rmax = r.Max + l.rmax; 否则rmax = r.rmax;
Max: 形如小白逛公园,Max = max(l.Max.r.Max,l.rmax + r.lmax);

然后query时根据情况二分即可。

# include <bits/stdc++.h>
using namespace std;
const int N = 50005;
int n,m;
struct node
{
    int val,lazy;
    int lmax,rmax,Max;
}T[N << 2];

void build(int root,int l,int r)
{
    if(l == r) 
    {
        T[root].val = T[root].lazy = 0,T[root].lmax = T[root].rmax = T[root].Max = 1;
        return;
    }
    int mid = (l + r) >> 1;build(root << 1,l,mid),build(root << 1 | 1,mid + 1,r);
    T[root].val = T[root << 1].val + T[root << 1 | 1].val,T[root].lmax = T[root].rmax = T[root].Max = (r - l + 1);
    return;
}

void pushdown(int root,int l,int r)
{
    if(T[root].lazy == 0) return;
    int mid = (l + r) >> 1;
    if(T[root].lazy == -1)
    {
        T[root << 1].lmax = T[root << 1].rmax = T[root << 1].Max = (mid - l + 1);
        T[root << 1 | 1].lmax = T[root << 1 | 1].rmax = T[root << 1 | 1].Max = (r - mid);
        T[root << 1].lazy = T[root << 1 | 1].lazy = -1;
    }
    else if(T[root].lazy == 1)
    {
        T[root << 1].lmax = T[root << 1].rmax = T[root << 1].Max = T[root << 1 | 1].lmax = T[root << 1 | 1].rmax = T[root << 1 | 1].Max = 0;
        T[root << 1].lazy = T[root << 1 | 1].lazy = 1;
    }
    T[root].lazy = 0;return;
}

void pushup(int root,int l,int r)
{
    int mid = (l + r) >> 1;
    if(T[root << 1].Max == (mid - l + 1)) // full 0
    {
        T[root].lmax = T[root << 1].Max + T[root << 1 | 1].lmax;
    }
    else T[root].lmax = T[root << 1].lmax;
    if(T[root << 1 | 1].Max == (r - mid))
    {
        T[root].rmax = T[root << 1 | 1].Max + T[root << 1].rmax;
    }
    else T[root].rmax = T[root << 1 | 1].rmax;
    T[root].Max = max(T[root << 1].Max,max(T[root << 1 | 1].Max,T[root << 1].rmax + T[root << 1 | 1].lmax));
    return;
}

void update(int root,int l,int r,int s,int t,int d)
{
    if(l <= s && t <= r)
    {
        if(d == 1) T[root].lmax = T[root].rmax = T[root].Max = 0;
        else T[root].lmax = T[root].rmax = T[root].Max = t - s + 1;
        T[root].lazy = d;
        return;
    }
    int mid = (s + t) >> 1;
    pushdown(root,s,t);
    if(l <= mid) update(root << 1,l,r,s,mid,d);
    if(r > mid) update(root << 1 | 1,l,r,mid + 1,t,d);
    pushup(root,s,t);
    return;
 }

 int query(int root,int l,int r,int d)
 {
     pushdown(root,l,r);
    //  pushup(root,l,r);
     if(l == r) return l;
    int mid = (l + r) >> 1;
    if(T[root << 1].Max >= d)
    {
        return query(root << 1,l,mid,d);
    }
    if(T[root << 1].rmax + T[root << 1 | 1].lmax >= d)
    {
        return mid - T[root << 1].rmax + 1;
    }
    else return query(root << 1 | 1,mid + 1,r,d);
 }

int main(void)
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--)
    {
        int d,x;
        int opt;scanf("%d",&opt);
        if(opt == 1)
        {
            scanf("%d",&d);
            if(T[1].Max >= d)
            {
                x = query(1,1,n,d);
                printf("%d\\n",x);
                update(1,x,x + d - 1,1,n,1);
            }
            else printf("%d\\n",0);
        }
        else
        {
            scanf("%d%d",&x,&d);
            update(1,x,x + d - 1,1,n,-1);
        }
    }
    return 0;
}

以上是关于ACWing 261 旅馆(Hotel)的主要内容,如果未能解决你的问题,请参考以下文章

1593: [Usaco2008 Feb]Hotel 旅馆 (线段树)

bzoj 1593: [Usaco2008 Feb]Hotel 旅馆

bzoj1593 [Usaco2008 Feb]Hotel 旅馆

[BZOJ1593][Usaco2008 Feb]Hotel 旅馆

BZOJ1593: [Usaco2008 Feb]Hotel 旅馆

建筑改造——老饭店变身清水红砖波纹HIVE HOTEL精品旅馆