题目链接:http://poj.org/problem?id=3667
题意:给你一些空房子,有一些人来住房子,每次询问m个人能不能住上,需要住连续的空房子
空房子用0表示,被占用的房子用1表示,然后用线段树维护一个区间的最长连续0的长度,左连续,右连续
区间合并的时候,最长的连续0的长度,从三个值里取最大值,max(左儿子的最大值,右儿子的最大值,左儿子的最长右连续+右儿子的最长左连续)
具体看代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
const int maxn = 50000 + 10;
struct node{
int l, r, lazy, maxx;
int maxl, maxr, len;
}e[maxn << 2];
void build(int l, int r, int cur) {
e[cur].l = l;
e[cur].r = r;
e[cur].lazy = 0;
e[cur].len = e[cur].maxx = e[cur].maxl = e[cur].maxr = r - l + 1;
if(l == r){
return;
}
int mid = l + r >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
}
void pushup(int cur){
//cout <<e[cur << 1].maxl <<" "<<e[cur << 1].maxr << " "<<e[cur << 1 | 1].maxl <<" "<<e[cur << 1 |1].maxr<<endl;
e[cur].maxl = e[cur << 1].maxl;
e[cur].maxr = e[cur << 1 | 1].maxr;
if(e[cur << 1].maxl == e[cur << 1].len) e[cur].maxl = e[cur << 1].len + e[cur << 1 | 1].maxl;
if(e[cur << 1 | 1].maxr == e[cur << 1 | 1].len) e[cur].maxr = e[cur << 1].maxr + e[cur << 1 | 1].len;
e[cur].maxx = max(e[cur << 1].maxx, max(e[cur << 1 | 1].maxx, e[cur << 1].maxr + e[cur << 1 | 1].maxl));
}
void pushdown(int cur){
if(e[cur].lazy != 0){
if(e[cur].lazy == 1){
e[cur << 1].lazy = e[cur << 1 | 1].lazy = 1;
e[cur << 1].maxx = e[cur << 1].maxl = e[cur << 1].maxr = 0;
e[cur << 1 | 1].maxx = e[cur << 1 | 1].maxl = e[cur << 1 | 1].maxr = 0;
e[cur].lazy = 0;
}
else {
e[cur << 1].lazy = e[cur << 1 | 1].lazy = -1;
e[cur << 1].maxx = e[cur << 1].maxl = e[cur << 1].maxr = e[cur << 1].len;
e[cur << 1 | 1].maxx = e[cur << 1 | 1].maxl = e[cur << 1 | 1].maxr = e[cur << 1 | 1].len;
e[cur].lazy = 0;
}
}
}
void update(int l, int r, int cur, int cl, int cr, int val){
if(cl <= l && r <= cr){
//cout << l << " "<<r << " "<<cur << endl;
e[cur].lazy = val;
if(val == 1)
e[cur].maxl = e[cur].maxr = e[cur].maxx = 0;
else
e[cur].maxl = e[cur].maxr = e[cur].maxx = e[cur].len;
return;
}
pushdown(cur);
//cout << l << " "<< r<<" "<< cur <<endl;
int mid = l + r >> 1;
if(cl <= mid) update(l, mid , cur << 1, cl, cr, val);
if(cr > mid) update(mid + 1, r, cur << 1 | 1, cl, cr ,val);
pushup(cur);
//cout << "e[cur].maxx = "<<e[cur].maxx << endl;
}
int query(int l, int r, int cur, int val) {
if(l == r) {
return l;
}
pushdown(cur);
int mid = l + r >> 1;
if(e[cur << 1].maxx >= val) return query(l, mid, cur << 1, val);
else if(e[cur << 1].maxr + e[cur << 1 | 1].maxl >= val) return e[cur << 1 | 1].l + val - e[cur << 1].maxr - 1;
else return query(mid + 1, r, cur << 1 | 1, val);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
build(1, n, 1);
while(m--) {
int op, x, d;
scanf("%d%d", &op, &x);
if(op == 1) {
if(e[1].maxx < x) {
printf("0\n");
}
else {
int l = query(1, n, 1, x);
printf("%d\n", l - x + 1);
update(1, n, 1, l - x + 1, l, 1);
}
}
else {
scanf("%d", &d);
update(1, n, 1, x, x + d - 1, -1);
}
}
return 0;
}