POJ3667——线段树区间合并(未搞透)——Hotel

The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation residence. This immense hotel has N (1 ≤ N≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).

The cows and other visitors arrive in groups of size Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of r to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1). Some (or all) of those rooms might be empty before the checkout.

Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Line i+1 contains request expressed as one of two possible formats: (a) Two space separated integers representing a check-in request: 1 and D(b) Three space-separated integers representing a check-out: 2, Xi, and Di

Output

* Lines 1.....: For each check-in request, output a single line with a single integer r, the first room in the contiguous sequence of rooms to be occupied. If the request cannot be satisfied, output 0.

Sample Input

10 6
1 3
1 3
1 3
1 3
2 5 5
1 6

Sample Output

1
4
7
0
5
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAX = 50000 + 10;
int lazy[MAX<<2];
int n, m;
struct edge{
    int lsum, rsum, msum;
}node[MAX<<2];

void build(int rt, int l, int r)
{
    lazy[rt] = -1;
    node[rt].lsum = node[rt].rsum = node[rt].msum = r - l + 1;
    if(l == r) return;
    int mid = l + r >> 1;
    build(rt*2, l, mid);
    build(rt*2+1, mid + 1, r);
}

void push_up(int rt, int len)
{
    node[rt].lsum = node[rt*2].lsum;
    node[rt].rsum = node[rt*2+1].rsum;
    if(node[rt].lsum == len - (len >> 1))
            node[rt].lsum += node[rt*2+1].lsum;
    if(node[rt].rsum == len >> 1)
            node[rt].rsum += node[rt*2].rsum;
    node[rt].msum = max(node[rt*2].rsum + node[rt*2+1].lsum, max(node[rt*2].msum, node[rt*2+1].msum));
}

void push_down(int rt, int len)
{
   lazy[rt*2] = lazy[rt*2+1] = lazy[rt];
   node[rt*2].lsum = node[rt*2].rsum = node[rt*2].msum = lazy[rt] ? 0 : len - (len >> 1);
   node[rt*2+1].lsum = node[rt*2+1].rsum = node[rt*2+1].msum = lazy[rt] ? 0 : len >> 1;
   lazy[rt] = -1;
}

void update(int l, int r, int val, int rt, int L, int R)
{
    if(L <= l && R >= r){
        node[rt].lsum = node[rt].rsum = node[rt].msum = val ? 0 : r - l + 1;
        lazy[rt] = val;
        return ;
    }if(~lazy[rt]) push_down(rt, r - l + 1);
    int mid = l + r >> 1;
    if(L <= mid) update(l, mid, val ,rt*2, L, R);
    if(R > mid)  update(mid+1, r, val, rt*2+1, L, R);
    push_up(rt, r - l + 1);
}

int query(int w, int rt, int l, int r)
{
    if(l == r) return l;
    if(~lazy[rt]) push_down(rt, r - l + 1);
    int mid = l + r >> 1;
    if(node[rt*2].msum >= w)
        return query(w, rt*2, l, mid);
    else if(node[rt*2].rsum + node[rt*2+1].lsum >= w){
        return mid - node[rt*2].rsum + 1;
    }
    else return query(w, rt*2+1, mid + 1, r);
}

int main()
{
    int flag;
    int x, y;
    while(~scanf("%d%d", &n, &m)){
        build(1, 1, n);
        while(m--){
        scanf("%d", &flag);
        if(flag == 1) {
            scanf("%d", &x);
            int ans = query(x, 1, 1, n);
            if(node[1].msum < x) printf("0\n");
            else {
            printf("%d\n", ans);
            update(1, n, 1, 1, ans, ans + x - 1);
            }
        }
        else {
            scanf("%d%d", &x, &y);
            update(1, n, 0, 1, x, x + y - 1);
        }
        }
    }
    return 0;
}

  

时间: 2024-10-06 12:10:31

POJ3667——线段树区间合并(未搞透)——Hotel的相关文章

poj3667 线段树 区间合并

1 //Accepted 3728 KB 1079 ms 2 //线段树 区间合并 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <queue> 7 #include <cmath> 8 #include <algorithm> 9 using namespace std; 10 /** 11 * This is a document

POJ-3667 线段树区间合并入门题

题意:长度为n的区间,m个操作,一开始都是0 1 x表示求出长度为x的0的连续区间的最左端,并把这个区间变成1 2 x y表示将区间[x,y]变成0 线段树的区间合并第一题: 每次维护左端连续区间长度ls.右端连续区间长度rs,最大连续长度ms 区间合并的注意点主要在push up操作: 每次更新了一段区间之后向上更新,首先,父区间的ls继承左子树的ls,父区间的rs继承右子树的rs 然后就是重点:左右区间合并之后中间部分可能是连续的!!! 所以:如果整个左.右子区间都是“满的”,父区间的ls和

【线段树区间合并】BZOJ1593-[Usaco2008 Feb]Hotel 旅馆

好无聊,以前写过没什么好讲的,水过.戳 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #define lson l,mid,rt<<1 5 #define rson mid+1,r,rt<<1|1 6 #define root 1 7 using namespace std; 8 const int MAXN=50000+50; 9 int n,m; 10 int ls

线段树 区间合并

poj3667 Hotel 区间合并入门题,照着代码打的, 题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边       2 a b:将[a,a+b-1]的房间清空思路:记录区间中最长的空房间,开三个数组,msum[rt]表示节点rt内连续的1的个数的最大值,lsum[rt]表示从节点rt左端点开始连续1的个数,rsum[rt]表示从节点rt右端点开始连续1的个数..线段树操作:update:区间替换 query:询问满足条件的最左端点 1 #include<iostream>

hdu4553约会安排(线段树区间合并)

链接 poj3667的加强版 当时的题解 这里只不过对于女神需要另开算,DS的占用的时间不加在女神身上,女神的时间都要加,清空的时候也都要算. 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath>

POJ 3667 Hotel 【线段树 区间合并 + Lazy-tag】

Hotel Time Limit: 3000MS Memory Limit: 65536K 链接:POJ 3667   Description The cows are journeying north to ThunderBay in Canada to gain cultural enrichment and enjoy a vacation on the sunnyshores of Lake Superior. Bessie, ever the competent travel agen

HDU 3911 Black And White(线段树区间合并)

Problem Description There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she wan

HDU 3308 LCIS (线段树区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1

HDU 5316 Magician(线段树区间合并入门)

本文纯属原创,转载请注明出处谢谢.http://blog.csdn.net/zip_fan. 题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5316 Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Fantasy magicians usually gain their ability