POJ 1823 Hotel【线段树】

POJ 1823 Hotel【线段树】http://poj.org/problem?id=1823

Hotel
Time Limit: 5000MS Memory Limit: 30000K
Total Submissions: 2031 Accepted: 869

Description

The "Informatics" hotel is one of the most luxurious hotels from Galaciuc. A lot of tourists arrive or leave this hotel in one year. So it is pretty difficult to keep the evidence of the occupied rooms. But this year the owner of the hotel decided to do some changes. That's why he engaged you to write an efficient program that should respond to all his needs. 

Write a program that should efficiently respond to these 3 types of instructions: 
type 1: the arrival of a new group of tourists 
A group of M tourists wants to occupy M free consecutive rooms. The program will receive the number i which represents the start room of the sequence of the rooms that the group wants to occupy and the number M representing the number of members of the group. It is guaranteed that all the rooms i,i+1,..,i+M-1 are free at that moment. 
type 2: the departure of a group of tourists 
The tourists leave in groups (not necessarilly those groups in which they came). A group with M members leaves M occupied and consecutive rooms. The program will receive the number i representing the start room of the sequence of the released rooms and the number M representing the number of members of the group. It is guaranteed that all the rooms i,i+1,..,i+M-1 are occupied. 
type 3: the owner's question 
The owner of the hotel may ask from time to time which is the maximal length of a sequence of free consecutive rooms. He needs this number to know which is the maximal number of tourists that could arrive to the hotel. You can assume that each room may be occupied by no more than one tourist. 

Input

On the first line of input, there will be the numbers N (3 <= N <= 16 000) representing the number of the rooms and P (3 <= P <= 200 000) representing the number of the instructions. 

The next P lines will contain the number c representing the type of the instruction: 
  • if c is 1 then it will be followed (on the same line) by 2 other numbers, i and M, representing the number of the first room distributed to the group and the number of the members 
  • if c is 2 then it will be followed (on the same line) by 2 other numbers, i and M, representing the number of the first room that will be released and the number of the members of the group that is leaving 
  • if c is 3 then it will not be followed by any number on that line, but the program should output in the output file the maximal length of a sequence of free and consecutive rooms

Output

In the output you will print for each instruction of type 3, on separated lines, the maximal length of a sequence of free and consecutive rooms. Before the first instruction all the rooms are free.

Sample Input

12 10
3
1 2 3
1 9 4
3
2 2 1
3
2 9 2
3
2 3 2
3 

Sample Output

12
4
4
6
10

Source

[Submit]   [Go Back]   [Status]   [Discuss]

【题意】有n个房间标号1~n,起初全是空的,每个房间只能住一人;有三种不同的操作:1 a b表示从a房间开始住进去b个人;2 a b表示从a房间开始离开b个人;3 表示查询当前状态最长的连续空房间个数。

【分析】线段树

【代码如下】

//1823	Accepted	924K    3500MS	C++	3480B
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 16000 + 10;

struct hotel
{
    int l, r;
    int in;
    //记录该区间是否被覆盖,0代表未覆盖,1代表部分覆盖,2代表完全覆盖
    int maxl, mmax, maxr;
    //记录节点,左边的最大长度maxl,右边的最大长度maxr,和该节点区间的最大长度mmax
}tree[maxn*4];

void build_tree(int l, int r, int u)//建树
{
    tree[u].l = l; tree[u].r = r; tree[u].in = 0;
    if(l == r){
        tree[u].mmax = tree[u].maxr = tree[u].maxl = 1;
        return ;
    }
    int mid = (l+r)/2;
    build_tree(l, mid, u*2);
    build_tree(mid+1, r, u*2+1);
    tree[u].mmax = tree[u].maxr = tree[u].maxl = tree[u*2].mmax + tree[u*2+1].mmax;
}

void update(int u)//更新节点的最大值
{
    if(!tree[u*2].in)//如果该节点的左子树未被覆盖,则该节点左边maxl的最大值为:左子树的最大值加上右子树的左边值
        tree[u].maxl = tree[u*2].mmax + tree[u*2+1].maxl;
    else
        tree[u].maxl = tree[u*2].maxl;//否则该节点的左边值就等于左子树的左边值
    if(!tree[u*2+1].in)//同理更新节点的右值
        tree[u].maxr = tree[u*2+1].mmax + tree[u*2].maxr;
    else
        tree[u].maxr = tree[u*2+1].maxr;
    //下面一步是更新节点的mmax
    int maxl = max(tree[u].maxl, tree[u].maxr);//找出节点左右值的最大值。
    int maxm = tree[u*2].maxr + tree[u*2+1].maxl;//该节点左子树的右值加右子树的左值(即该父节点区间的中间值)
    int maxr = max(tree[u*2].mmax, tree[u*2+1].mmax);//左右子树的最大值
    int maxmax = max(max(maxl, maxm), maxr);
    tree[u].mmax = maxmax;//更新最大值
    if(tree[u*2].in == tree[u*2+1].in)
        tree[u].in = tree[u*2].in;
}

void insert(int l, int r, int u)//插入
{
    if(l==tree[u].l && tree[u].r==r)//如果区间相等
    {
        tree[u].in=2;//则完全覆盖
        tree[u].maxl=tree[u].maxr=tree[u].mmax=0;//长度为0
        return ;
    }
    if(!tree[u].in)//如果没被覆盖
    {
        tree[u].in=1;
        tree[u*2].in=0;
        tree[u*2+1].in=0;
        //更新左右子树的最大值为区间长度
        tree[u*2].maxl=tree[u*2].maxr=tree[u*2].mmax=tree[u*2].r-tree[u*2].l+1;
        tree[u*2+1].maxl=tree[u*2+1].mmax=tree[u*2+1].maxr=tree[u*2+1].r-tree[u*2+1].l+1;
    }
    //向下递归
    int mid=(tree[u].l+tree[u].r)/2;
    if(r <= mid)
        insert(l, r, u*2);
    else if(l > mid)
        insert(l, r, u*2+1);
    else
    {
        insert(l, mid, u*2);
        insert(mid+1, r, u*2+1);
    }
    update(u);//更新节点的最大值
}

void remove(int l,int r,int u)//撤离同插入
{
    if(l==tree[u].l&&tree[u].r==r)//如果相等
    {
        tree[u].in=0;//则全部移除,为0。
        tree[u].maxl=tree[u].maxr=tree[u].mmax=tree[u].r-tree[u].l+1;//更新最大值为区间长度
        return ;
    }
    if(tree[u].in==2)//如果该节点被完全覆盖
    {
        tree[u].in=1;
        tree[u*2].in=2;
        tree[u*2+1].in=2;
        //更新左右子树的最大值为0.(完全覆盖)
        tree[u*2].maxl=tree[u*2].mmax=tree[u*2].maxr=0;
        tree[u*2+1].maxl=tree[u*2+1].mmax=tree[u*2+1].maxr=0;
    }
    //向下递归
    int mid=(tree[u].l+tree[u].r)/2;
    if(r<=mid)
        remove(l, r, u*2);
    else if(l>mid)
        remove(l, r, u*2+1);
    else
    {
        remove(l, mid, u*2);
        remove(mid+1, r, u*2+1);
    }
    update(u);//更新节点的最大值
}

int main()
{
    int n, m, k, a, b;
    scanf("%d %d", &n, &m);
    build_tree(1, n, 1);
    while(m--)
    {
        scanf("%d", &k);
        if(k==1){
            scanf("%d %d", &a, &b);
            insert(a, a+b-1, 1);
        }
        else if(k==2){
            scanf("%d %d", &a, &b);
            remove(a, a+b-1, 1);
        }
        else
            printf("%d\n", tree[1].mmax);
    }
    return 0;
}


深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值