POJ1823 Hotel(线段树)

题目链接:

  http://poj.org/problem?id=1823

题目描述:

Hotel
 

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

 

题目大意:

  旅馆看作一维数组,有客为 1,无客为 0

  三种操作,1 表示 l - r 范围内住客,2 表示 l - r 范围内客人离开,3 表示查询连续的空房数

思路:

  线段树维护每个区间最长连续空房数 tree[N],左连续空房数 treel[N],和右连续空房数 treer[N]

  合并时,若左子区间的左连续空房数(treel[ id << 1 ])与左子空间的大小相同,则 treel[ id ] = mid - l +1 +treel[ id << 1 | 1 ]

  否则为 treel[ id << 1 ],右端同理

  而在更新时注意打 lazy-tag,否则会超时

 

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N = 16010;
 8 
 9 int n, p, treel[4 * N], treer[4 * N], tree[4 * N], lazy[4 * N];
10 
11 void build(int l, int r, int id) {
12     if (l == r) { treel[id] = treer[id] = tree[id] = 1; lazy[id] = -1; return; }
13     int mid = (l + r) >> 1;
14     build(l, mid, id << 1);
15     build(mid + 1, r, id << 1 | 1);
16     if (treel[id << 1] == mid - l + 1)treel[id] = mid - l + 1 + treel[id << 1 | 1];
17     else treel[id] = treel[id << 1];
18     if (treer[id << 1 | 1] == r - mid)treer[id] = r - mid + treer[id << 1];
19     else treer[id] = treer[id << 1 | 1];
20     tree[id] = tree[id << 1] + tree[id << 1 | 1];
21     lazy[id] = 0;
22 }
23 
24 void update_lazy(int l, int r, int mid, int id) {
25     if (lazy[id] == 0) {
26         lazy[id] = -1; lazy[id << 1] = lazy[id << 1 | 1] = 0;
27         tree[id << 1] = treel[id << 1] = treer[id << 1] = mid - l + 1;
28         tree[id << 1 | 1] = treel[id << 1 | 1] = treer[id << 1 | 1] = r - mid;
29     } else if (lazy[id] == 1) {
30         lazy[id] = -1; lazy[id << 1] = lazy[id << 1 | 1] = 1;
31         tree[id << 1] = treel[id << 1] = treer[id << 1] =
32             tree[id << 1 | 1] = treel[id << 1 | 1] = treer[id << 1 | 1] = 0;
33     }
34 }
35 
36 void add(int l, int r, int a, int b, int id) {
37     if (l >= a&&r <= b) {
38         tree[id] = treel[id] = treer[id] = 0;
39         lazy[id] = 1;
40         return;
41     }
42     int mid = (l + r) >> 1;
43     if (lazy[id] != -1)update_lazy(l, r, mid, id);
44     if (mid >= a)add(l, mid, a, b, id << 1);
45     if (mid < b)add(mid + 1, r, a, b, id << 1 | 1);
46     int ans = max(tree[id << 1], tree[id << 1 | 1]);
47     tree[id] = max(ans, treer[id << 1] + treel[id << 1 | 1]);
48     if (treel[id << 1] == mid - l + 1)treel[id] = mid - l + 1 + treel[id << 1 | 1];
49     else treel[id] = treel[id << 1];
50     if (treer[id << 1 | 1] == r - mid)treer[id] = r - mid + treer[id << 1];
51     else treer[id] = treer[id << 1 | 1];
52 }
53 
54 void m_minus(int l, int r, int a, int b, int id) {
55     if (l >= a&&r <= b) {
56         tree[id] = treel[id] = treer[id] = r - l + 1;
57         lazy[id] = 0;
58         return;
59     }
60     int mid = (l + r) >> 1;
61     if (lazy[id] != -1)update_lazy(l, r, mid, id);
62     if (mid >= a)m_minus(l, mid, a, b, id << 1);
63     if (mid < b)m_minus(mid + 1, r, a, b, id << 1 | 1);
64     int ans = max(tree[id << 1], tree[id << 1 | 1]);
65     tree[id] = max(ans, treer[id << 1] + treel[id << 1 | 1]);
66     if (treel[id << 1] == mid - l + 1)treel[id] = mid - l + 1 + treel[id << 1 | 1];
67     else treel[id] = treel[id << 1];
68     if (treer[id << 1 | 1] == r - mid)treer[id] = r - mid + treer[id << 1];
69     else treer[id] = treer[id << 1 | 1];
70 }
71 
72 int main() {
73     scanf("%d%d", &n, &p);
74     int op, a, b;
75     build(1, n, 1);
76     for (int i = 0; i < p; ++i) {
77         scanf("%d", &op);
78         if (op == 1) {
79             scanf("%d%d", &a, &b);
80             add(1, n, a, a + b - 1, 1);
81         } else if (op == 2) {
82             scanf("%d%d", &a, &b);
83             m_minus(1, n, a, a + b - 1, 1);
84         } else printf("%d\n", tree[1]);
85     }
86 }

 

posted @ 2017-07-12 14:22  hyp1231  阅读(141)  评论(0编辑  收藏  举报