HDU 3367 Hotel

参照这个博客的做法:请戳 ,还有这个的讲解:

询问区间中满足条件的连续最长区间通常属于区间合并问题。

节点增加4个域,lx:从区间左边数连续空房间的数目。rx:从区间右边数连续空房间的数目。ax:该区间中连续空房间的总数目

col:记录该区间住人的状态,1表示全住满,0表示全空,-1表示有可以住的房间。

查询是否有连续空房间数目num的时候,先查询左边,当tree[v].lx >= num的时候递归左区间;再查询中间,当tree[v*2].lx +tree[v*2+1].rx >= num直接返回最左边端点;最后查询右边,当tree[v].rx>=num递归右区间。col记录该区间的状态,利用了Lazy思想,即当tree[v].col == 1或tree[v].col == 0 时(房间全住满或全不住的情况),要先把这个状态传递到左右子树,并把这个区间的col置为-1。

更新区间[st,st+num-1],即将该区间全置为空或置为满的时候,要先把区间的状态(全空或全满)传递给左右子树,然后递归,最后再把左右子树的状态更新上来,因为子树状态改变,父亲状态肯定也会改变。

看了一下午,终于理解了,看着博客敲得,原谅我是手残=。=


Description

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

Source

USACO 2008 February Gold

哎,一把心酸泪。涉及到lazy思想,和标记=。=,吃饭回来再注释

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1

const int maxn = 50005;
int lsum[maxn<<2] , rsum[maxn<<2] , msum[maxn<<2];
int cover[maxn<<2];

void PushDown(int rt,int m) {
    if (cover[rt] != -1) {
        cover[rt<<1] = cover[rt<<1|1] = cover[rt];
        msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : m - (m >> 1);
        msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : (m >> 1);
        cover[rt] = -1;
    }
}
void PushUp(int rt,int m) {
    lsum[rt] = lsum[rt<<1];
    rsum[rt] = rsum[rt<<1|1];
    if (lsum[rt] == m - (m >> 1)) lsum[rt] += lsum[rt<<1|1];
    if (rsum[rt] == (m >> 1)) rsum[rt] += rsum[rt<<1];
    msum[rt] = max(lsum[rt<<1|1] + rsum[rt<<1] , max(msum[rt<<1] , msum[rt<<1|1]));
}
void build(int l,int r,int rt) {
    msum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
    cover[rt] = -1;
    if (l == r) return ;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}
void update(int L,int R,int c,int l,int r,int rt) {
    if (L <= l && r <= R) {
        msum[rt] = lsum[rt] = rsum[rt] = c ? 0 : r - l + 1;
        cover[rt] = c;
        return ;
    }
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    if (L <= m) update(L , R , c , lson);
    if (m < R) update(L , R , c , rson);
    PushUp(rt , r - l + 1);
}
int query(int w,int l,int r,int rt) {
    if (l == r) return l;
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    if (msum[rt<<1] >= w) return query(w , lson);
    else if (rsum[rt<<1] + lsum[rt<<1|1] >= w) return m - rsum[rt<<1] + 1;
    return query(w , rson);
}
int main() {
    int n,m;
    int u,v,w;
    scanf("%d%d",&n,&m);
    build(1 , n , 1);
    while (m --)
    {
        scanf("%d",&u);
        if (u== 1)
        {
            scanf("%d",&w);
            if (msum[1] < w)
                puts("0");
            else
            {
                int pos= query(w, 1 , n , 1);
                printf("%d\n",pos);
                update(pos , pos + w - 1 , 1 , 1 , n , 1);
            }
        } else {
            scanf("%d%d",&v,&w);
            update(v, v + w - 1 , 0 , 1 , n , 1);
        }
    }
    return 0;
}

HDU 3367 Hotel

时间: 2024-08-04 15:57:41

HDU 3367 Hotel的相关文章

HDU 3367 Pseudoforest(伪森林)(并查集)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3367 题意:在图论中,如果一个森林中有很多连通分量,并且每个连通分量中至多有一个环,那么这个森林就称为伪森林. 现在给出一个森林,求森林包含的最大的伪森林,其大小通过所有边的权值之和来比较. 分析: 1.一开始想的是:在每个连通分量中求一个最大生成树,然后加一条最大的边,再把每个连通分量算出来的值加起来,但WA了.这并不是最优的,因为还存在这种情况:一个连通分量里最初有两个环,但是伪森林要求最多一个

HDU 3367 Pseudoforest 最大生成树

题目来源:HDU 3367 Pseudoforest 题意:每个连通块最多可以有一个环 求最大的森林 思路:考虑最大生成树 如果祖先一样没有环 那就合并 如果祖先不一样 如果2棵树都没有环 合并 如果有1棵树有环 合并 标记该棵树有环 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100010; struct edge { i

hdu 2686 Matrix &amp;&amp; hdu 3367 Matrix Again (最大费用最大流)

Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1394    Accepted Submission(s): 758 Problem Description Yifenfei very like play a number game in the n*n Matrix. A positive integer number

hdu 3367 Pseudoforest (最小生成树)

Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1526    Accepted Submission(s): 580 Problem Description In graph theory, a pseudoforest is an undirected graph in which every connec

HDU 2585 Hotel(字符串的模糊匹配+递归)

Problem Description Last year summer Max traveled to California for his vacation. He had a great time there: took many photos, visited famous universities, enjoyed beautiful beaches and tasted various delicious foods. It is such a good trip that Max

hdu 3367 Pseudoforest(并查集)

题意:求图的一最大联通子图,其中最多包含一个环. 思路:利用求最小生成树的方法(kruskal),排序时从大到小排序.连接时有三种情况: 1.一边有环,一边没有(可能两点已经在同一集合,也可能不在) 2.两边都没有环 3.两边都有环 如图: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #in

HDU 3367 Pseudoforest

https://vjudge.net/problem/HDU-3367 题意: 一个伪森林是一个每个连通分量至多有一个环的无向图,给出一个图,图中不包含重边和圈,请你求出这个图的权值最大的伪森林. 思路: 一开始想的是用最大生成树,然后加一条最大的不在生成树中的边,wa了,真是可笑题意都没有理解清楚.题中的图可以是非连通的. 之后看了题解,发现是用并查集的思路,先把边从大到小进行排序,之后对于每一条边,我们看它的两个点a,b. 有2大的种情况: 1.a,b在一个连通分量中,并且他们没有被标记,则

(最大生成树) hdu 3367

Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1957    Accepted Submission(s): 756 Problem Description In graph theory, a pseudoforest is an undirected graph in which every connec

hdu 3367 Pseudoforest【伪森林】

Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1929    Accepted Submission(s): 745 Problem Description In graph theory, a pseudoforest is an undirected graph in which every conne