POJ 3667

原创 2013年12月02日 18:32:22

  题意:  一个旅馆有N个连续的空房间。。。

  接下来一些操作   

    进来的旅客都需要有一些连续的空房间

如果有则输出首个房间的位置。如果没有就输出0.

  或者是在某个位置开始空出连续的一些房间。(房间原来就可以是空的)  


思路:

      首先建立线段树。。

    每个区间要保存该区间内从左数的空房间数,lk,从右数的空房间数rk和最大空房间数mk.

每次更新改区间的时候就是分情况来更新lk,rk,mk这三个数据。

  剩下的没有什么需要注意的了。。。只要注意查找区间时的顺序应该是从左子树,左子树的rk+右子树的lk,右子树就可以了。

贴上代码。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int m;
struct tree{
   int left;
   int right;
   int lk;
   int mk;
   int rk;
   int flag;
   int lazy;
}tree[800000];
void inset(int inst,int le,int ri)
{
    tree[inst].left=le;
    tree[inst].right=ri;
    tree[inst].lk=(ri-le+1);
    tree[inst].rk=(ri-le+1);
    tree[inst].mk=(ri-le+1);
    tree[inst].flag=0;
    tree[inst].lazy=2;
    if(le==ri) return ;
    int mid=(le+ri)>>1;
    inset(2*inst,le,mid);
    inset(2*inst+1,mid+1,ri);

}
void cd(int inst)
{  //cout<<"cd"<<endl;
    if(tree[inst].lazy==0)
    {  //cout<<"cd1 "<<inst<<endl;
        tree[2*inst].lk=(tree[2*inst].right-tree[2*inst].left+1);
        tree[2*inst].rk=(tree[2*inst].right-tree[2*inst].left+1);
        tree[2*inst].mk=(tree[2*inst].right-tree[2*inst].left+1);
        tree[2*inst+1].lk=(tree[2*inst+1].right-tree[2*inst+1].left+1);
        tree[2*inst+1].rk=(tree[2*inst+1].right-tree[2*inst+1].left+1);
        tree[2*inst+1].mk=(tree[2*inst+1].right-tree[2*inst+1].left+1);
        tree[inst].flag=1;
        tree[2*inst].lazy=0;tree[2*inst+1].lazy=0;
        tree[inst].lazy=2;
    }
    else if(tree[inst].lazy==1)
    { //cout<<"cd2 "<<inst<<endl;
        tree[2*inst].lk=0;
        tree[2*inst].mk=0;
        tree[2*inst].rk=0;
        tree[2*inst+1].lk=0;
        tree[2*inst+1].mk=0;
        tree[2*inst+1].rk=0;
        tree[inst].flag=1;
        tree[2*inst].lazy=1;tree[2*inst+1].lazy=1;
        tree[inst].lazy=2;
    }
}
void add(int inst,int le,int ri)
{
    if(tree[inst].left==le&&tree[inst].right==ri)
    {
        tree[inst].lk=(ri-le+1);
        tree[inst].mk=(ri-le+1);
        tree[inst].rk=(ri-le+1);
        tree[inst].lazy=0;
        tree[inst].flag=0;

        //cout<<tree[inst].mk<<endl;
        return ;
    }
    cd(inst);
    tree[inst].flag=1;
    if(tree[inst].left==tree[inst].right) return ;
    int mid=(tree[inst].left+tree[inst].right)>>1;
    if(ri<=mid)
        add(2*inst,le,ri);
    else if(le>mid)
        add(2*inst+1,le,ri);
    else
    {
        add(2*inst,le,mid);
        add(2*inst+1,mid+1,ri);
    }
}
void add1(int inst,int le,int ri)
{
     //cout<<inst<<" "<<le<<" "<<ri<<endl;
    if(tree[inst].left==le&&tree[inst].right==ri)
    {  //cout<<tree[inst].left<<" "<<tree[inst].right<<endl;
        tree[inst].lk=0;
        tree[inst].mk=0;
        tree[inst].rk=0;
        tree[inst].lazy=1;
        tree[inst].flag=0;
        return ;
    }
     cd(inst);
     tree[inst].flag=1;
     if(tree[inst].left==tree[inst].right) return ;
    int mid=(tree[inst].left+tree[inst].right)>>1;
    if(ri<=mid)
        add1(2*inst,le,ri);
    else if(le>mid)
        add1(2*inst+1,le,ri);
    else
    {
        add1(2*inst,le,mid);
        add1(2*inst+1,mid+1,ri);
    }
}
void flag(int inst)
{  //cout<<"flag"<<endl;
    if(tree[inst].lazy!=2) cd(inst);
    //if(inst==3) cout<<tree[2*inst].mk<<" "<<tree[2*inst+1].mk<<"  1"<<endl;
    if(tree[2*inst].flag!=0)
        flag(2*inst);
    if(tree[2*inst+1].flag!=0)
        flag(2*inst+1);
    tree[inst].flag=0;
    tree[inst].lazy=2;
    tree[inst].lk=tree[2*inst].lk;
    tree[inst].rk=tree[2*inst+1].rk;
    tree[inst].mk=max(tree[2*inst].mk,max(tree[2*inst+1].mk,tree[2*inst].rk+tree[2*inst+1].lk));
    //if(inst==3) cout<<tree[inst].mk<<"  2"<<endl;
    if(tree[2*inst].lk==(tree[2*inst].right-tree[2*inst].left+1))
        tree[inst].lk=tree[2*inst].lk+tree[2*inst+1].lk;
    if(tree[2*inst+1].rk==(tree[2*inst+1].right-tree[2*inst+1].left+1))
        tree[inst].rk=tree[2*inst].rk+tree[2*inst+1].rk;
        //cout<<inst<<" "<<tree[inst].lk<<" "<<tree[2*inst].lk<<"  lk"<<endl;
        //cout<<inst<<" "<<tree[inst].rk<<" "<<tree[2*inst+1].rk<<"  rk"<<endl;
        //cout<<inst<<" "<<tree[inst].mk<<" "<<tree[2*inst].mk<<"  mk"<<endl;
}
void query(int inst,int k)
{
    //cout<<tree[3].mk<<" 1"<<endl;
    if(tree[inst].flag!=0)
        flag(inst);
        //cout<<tree[3].mk<<" 2"<<endl;
    //cout<<inst<<" "<<tree[inst].mk<<" "<<tree[2*inst].mk<<" "<<tree[2*inst+1].mk<<endl;
    if(tree[inst].right==tree[inst].left)
    {  if(k==1)
       {   if(tree[inst].mk==1)
          {
              m=tree[inst].left;
              //cout<<"add1"<<tree[inst].left<<" "<<tree[inst].right<<endl;
           add1(inst,tree[inst].left,tree[inst].right);
          }
          else m=0;
       }
        else m=0;
        //cout<<m<<endl;
        return ;
    }
         cd(inst);
    if(tree[inst].mk>=k)
        {   tree[inst].flag=1;
            tree[inst].lazy=2;
            if(tree[2*inst].mk>=k)
            {  //cout<<m<<endl;
                query(2*inst,k);
            }
            else if(tree[2*inst].rk+tree[2*inst+1].lk>=k&&tree[2*inst].rk!=0)
            {     m=tree[2*inst].right-tree[2*inst].rk+1;
                    int t=tree[2*inst+1].left+k-tree[2*inst].rk-1;
                add1(inst,tree[2*inst].right-tree[2*inst].rk+1,tree[2*inst].right);
                add1(inst,tree[2*inst+1].left,t);

                //cout<<inst<<endl;
            }
            else if(tree[2*inst+1].mk>=k)
            { //cout<<inst<<endl;
                query(2*inst+1,k);
            }
        }
    else {  //cout<<"###"<<endl;
            m=0; return ;
    }
}
int main()
{
    int n,m1;
    while(scanf("%d%d",&n,&m1)!=EOF)
    {
        inset(1,1,n);

        while(m1--)
        {
            int x,a,b;
            scanf("%d",&x);
            if(x==1)
            {   m=0;
                scanf("%d",&a);
                //cout<<a<<endl;
                query(1,a);

                printf("%d\n",m);
               // cout<<"!!!  "<<tree[3].mk<<endl;
            }
            else
            {
                scanf("%d%d",&a,&b);
                add(1,a,a+b-1);
            }
        }
    }
}


相关文章推荐

poj 3667 hotel (线段树+区间合并)

以前学习过的线段树,在查询和更新的基础上加入了区间合并,利用延迟标志来实现这一方法 代码在这: #include #include #include using namespace std;...

POJ 3667 Hotel 线段树(区间合并)

链接:http://poj.org/problem?id=3667 题意:一家旅馆,不断有人入住,退房。入住的人要求房号连续,退房是连续房号的房间退掉。 思路:线段树LAZY-TAG+区间合并。相比于...

POJ 3667 Hotel (线段树求最长连续子序列)

http://poj.org/problem?id=3667题意:有一个线段,从1到n,下面m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作1 查询操作,找一段长度为W的没被覆盖的...

POJ 3667 Hotel 线段树

Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 11104 Accep...

Poj 3667 Hotel + Hdu 4553 约会安排 (线段树最左空区间)

题目链接:http://poj.org/problem?id=3667 题意:旅馆的N(1 ≤ n ≤ 50,000) 个房间初始时全为空。现在有M(1 ≤ m (1)1  X,要求得到连续的X...

poj 3667 最长空白段+查询最左连续段

Hotel 大体分析: 题意:从最左找连续空间,是否能找到。 解法:同poj1823。 //是1823的加强版,但是提交记录也是呵呵了。 //多的一个操作就是查询操...

【POJ 3667】Hotel

POJ 3667题意有n个房间和k个操作,最开始全部为空。操作1:输入一个数d,找出连续d个空房间,输出起点房间编号。若有多个输出最小的,如果不存在输出0。操作2:输入两个数x和d,清空从x开始的d个...
  • Ripped
  • Ripped
  • 2017年02月05日 12:21
  • 116

poj3667(线段树区间合并)

题目链接:poj3667 /*poj 3667 Hotel 线段树区间合并 题意: 操作1:询问是否有连续x间房间可以住,输出最左端的房间位置 操作2:顾客退房,将房间清空,表示没有人住 思路: ...

poj3667 Hotel

经典问题,就是线段树[L, R]上保存3个信息,分别表示以L开头最多连续的空格,R为结尾的最多连续空格,这段区间最大的连续空格。然后就可以写代码了。 (为什么我的线段树这么丑) #include us...

poj - 3667

#include #include using namespace std; #define MAX 50010 struct TreeNode { int left; in...
  • fyfcauc
  • fyfcauc
  • 2014年08月10日 17:28
  • 231
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 3667
举报原因:
原因补充:

(最多只允许输入30个字)