火山经营着一个停车场,假设的停车场有N车位(编号1-N)都在一条线上,最初所有车位都没停车。经常有人来定车位,
他要定连续的k(1 ≤ k ≤ N)个车位。火山要确定是否能够满足客人的要求,如果能,他要将这k个连续的车位安排在编
号最小的地方停下。若不能,则客人不停在火山的停车场。在某一时间,有些车会被车主开走了。火山的停车场很大,
火山想让学弟学妹写个程序帮助他。
Input
第1行输入 N 和 M。N是车位个数,M是(停车和开走车操作的总次数)
接下来M行,先输入操作类型(1或2)
若是1,表示有人来停车,再输入k
若是2,再输入l,r, 表示区间[l,l+r) 的车被开走了。
N (1 ≤ N ≤ 50,000) M (1 ≤ M < 50,000)
Output
当输入为1时,若火山的停车场有连续的k个车位,那么输出第一辆车停的最小的编号,否则输出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
Hint
样例解释:停车场有10个车位,6次操作。第一个人定了3个连续的车位时,第一辆车停在1的位置(即输出)
第二次预定3个连续的车位时,第一辆车停在4的位置,因为前三个位置被人定了。同理,下个人再来定时,
只能从编号为7的车位开始停。此时(1-9)的车位都停了车,下个人在来定三个位置,就不能满足他的要求,输出0.
2 5 5。 5开始的连续5个车位都被人开走了。现在(5-10)都是空的,下个人来定时3个位置,火山就把他们安排在
起始为置为5的位置。
一道线段树连续区间查询的题目 注意pushdown和pushup的方法 query的思路
#include<iostream>
const int maxn = 5e4 + 10;
int leaf[maxn];
int n, m;
using namespace std;
struct node{
int l, r;
int lsum, rsum;
int lazy, sum;
}tree[maxn * 3];
void pushup(int x){
tree[x].lsum = tree[x << 1].lsum;
tree[x].rsum = tree[x << 1 | 1].rsum;
if(tree[x].lsum == tree[x << 1].r - tree[x << 1].l + 1) tree[x].lsum += tree[x << 1 | 1].lsum;
if(tree[x].rsum == tree[x << 1 | 1].r - tree[x << 1 | 1].l + 1) tree[x].rsum += tree[x << 1].rsum;
tree[x].sum = max(tree[x << 1].rsum + tree[x << 1 | 1].lsum, max(tree[x << 1].sum, tree[x << 1 | 1].sum));
}
void pushdown(int x){
if(tree[x].lazy != -1){
tree[x << 1].lazy = tree[x << 1 | 1].lazy = tree[x].lazy;
int all = (tree[x << 1].r - tree[x << 1].l + 1) * tree[x].lazy;
tree[x << 1].lsum = tree[x << 1].rsum = tree[x << 1].sum = all;
all = (tree[x << 1 | 1].r - tree[x << 1 | 1].l + 1) * tree[x].lazy;
tree[x << 1 | 1].lsum = tree[x << 1 | 1].rsum = tree[x << 1 | 1].sum = all;
tree[x].lazy = -1;
}
}
void build(int i, int l, int r){
int mid = (l + r) >> 1;
tree[i].l = l;
tree[i].r = r;
tree[i].lsum = 0;
tree[i].rsum = 0;
tree[i].sum = 0;
tree[i].lazy = -1;
if(l == r){
tree[i].lsum = 1;
tree[i].rsum = 1;
tree[i].sum = 1;
leaf[l] = i;
return ;
}
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
pushup(i);
}
void update(int i, int l, int r, int val){
if(tree[i].l >= l && tree[i].r <= r){
tree[i].lazy = val;
int all = (tree[i].r - tree[i].l + 1) * val;
tree[i].lsum = tree[i].rsum = tree[i].sum = all;
return ;
}
else{
int mid = (tree[i].l + tree[i].r) >> 1;
pushdown(i);
if(r <= mid)
update(i << 1, l, r, val);
else if(l > mid)
update(i << 1 | 1, l, r, val);
else{
update(i << 1, l, mid, val);
update(i << 1 | 1, mid + 1, r, val);
}
}
pushup(i);
}
int query(int i, int m){
if(tree[i].l == tree[i].r)
return tree[i].l;
pushdown(i);
if(tree[i << 1].sum >= m)
return query(i << 1, m);
else if(tree[i << 1].rsum + tree[i << 1 | 1].lsum >= m)
return tree[i << 1].r - tree[i << 1].rsum + 1;
else
return query(i << 1 | 1, m);
}
int main(){
ios::sync_with_stdio(0);
while(cin >> n >> m){
build(1, 1, n);
for(int i = 1; i <= m; i++){
int a, b, c;
cin >> a;
if(a == 1){
cin >> b;
//cout << tree[1].sum << endl;
if(tree[1].sum >= b){
int w = query(1, b);
cout << w << endl;
update(1, w, w + b - 1, 0);
}
else
cout << 0 << endl;
}
else{
cin >> b >> c;
update(1, b, b + c - 1, 1);
}
}
}
}