POJ3667 Hotel

12 篇文章 0 订阅

线段树的题, 其中NODE节点中额外保存三个信息: lval保存的是本节点中, 以l为起点往右的最长连续空位; rval保存的是以r-1为起点往左的最长连续空位; sum保存的是本节点区间[l,r)中最长的连续空位.


/*******************************************************************************
# Author : Neo Fung
# Email : neosfung@gmail.com
# Last modified: 2012-01-18 20:11
# Filename: HDU1689 Just a Hook.cpp
# Description : 
******************************************************************************/
#ifdef _MSC_VER
#define DEBUG
#endif

#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <limits.h>
#include <algorithm>
#include <math.h>
#include <numeric>
#include <functional>
#include <ctype.h>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MAX 50010
using namespace std;

struct NODE
{
  int l,r,lval,rval,sum;
}node[MAX*4];

void init()
{
  memset(node,'\0',sizeof(node));
}

void build(const int &t , const int &l,const int &r)
{
  node[t].l=l;
  node[t].r=r;
  node[t].lval=node[t].rval=node[t].sum=r-l;
  if(l==r-1)
    return;
  int mid=(l+r)>>1;
  build(L(t),l,mid);
  build(R(t),mid,r);
}

void inline setNode(const int &t,const int &state)
{
  int len=node[t].r-node[t].l;
  node[t].lval=node[t].rval=node[t].sum=len*state;
}

int inline getLen(const int &t)
{
  return node[t].r-node[t].l;
}

void update(const int &t,const int &l,const int &r,const int &state)
{
  const int len=getLen(t);
  if(node[t].l>=l && node[t].r<=r)  //整段设置
  {
    setNode(t,state);
    return;
  }

  if(node[t].sum==len || node[t].sum==0)  //Lazy更新
  {
    int st=0;
    if(node[t].sum)
      st=1;
    setNode(L(t),st);
    setNode(R(t),st);
  }

  int mid=(node[t].l+node[t].r)>>1;
  if(l>=mid)
    update(R(t),l,r,state);
  else if(r<=mid)
    update(L(t),l,r,state);
  else
  {
    update(L(t),l,mid,state);
    update(R(t),mid,r,state);
  }

  node[t].lval=node[L(t)].lval;
  if(node[L(t)].lval==getLen(L(t)))
    node[t].lval+=node[R(t)].lval;
  node[t].rval=node[R(t)].rval;
  if(node[R(t)].rval==getLen(R(t)))
    node[t].rval+=node[L(t)].rval;
  node[t].sum=node[L(t)].rval+node[R(t)].lval;
  node[t].sum=max(node[t].sum,node[L(t)].sum);
  node[t].sum=max(node[t].sum,node[R(t)].sum);
}

int query(const int &t,const int &need)
{
  if(node[t].sum<need)
    return -1;
  if(node[t].l==node[t].r-1)
    return node[t].l;
  if(node[t].lval>=need)
    return node[t].l;
  if(node[L(t)].sum>=need)
    return query(L(t),need);
  else if(node[L(t)].rval+node[R(t)].lval>=need)
    return node[L(t)].r-node[L(t)].rval;
  else 
    return query(R(t),need);
}

int main(void)
{
#ifdef DEBUG  
    freopen("../stdin.txt","r",stdin);
    freopen("../stdout.txt","w",stdout); 
#endif  

  int n,m;
  int s,x,d;

  while(~scanf("%d%d",&n,&m))
  {
    init();
    build(1,0,n);
    while(m--)
    {
      scanf("%d",&s);
      if(s==1)
      {
        scanf("%d",&d);
        int ans=query(1,d);
        printf("%d\n",ans+1);
        if(ans>=0)
          update(1,ans,ans+d,0);
      }
      else
      {
        scanf("%d%d",&x,&d);
        update(1,x-1,x+d-1,1);
      }
    }
  }

  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值