POJ 3667 HOTEL

/*
第一类信息
ll, rr, len
递推求解
第二类信息
state.表示整个子树的性质
*/
#include
<stdio.h>
#include
<algorithm>
#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
using namespace std;

const int MAXN = 50002;
int N, M;
struct SegTree
{
int l, r;
int ll, rr; //最左边,右边可用连续区间长度
int len; //最长连续可用房间长度
int state; //0 空 1 满 -1 不空不满
int getMid(){
return (l + r) >> 1;
}
int getLen(){
return r - l + 1;
}
void init(int state1){
if(!state1){ //房间空闲
ll
= rr = len = getLen();
state
= state1;
}
else { //state = 1 区间房间全满
ll
= rr = len = 0;
state
= state1;
}
}
};
SegTree tree[MAXN
<< 2];

void bulid(int left, int right, int t){
tree[t].l
= left;
tree[t].r
= right;
tree[t].len
= tree[t].getLen();
tree[t].ll
= tree[t].rr = tree[t].len;
tree[t].state
= 0;
if(left == right)
return;
int mid = tree[t].getMid();
bulid(left, mid, L(t));
bulid(mid
+ 1, right, R(t));
}

void update(int left, int right, int state, int t){
if(tree[t].state == state){ //整个区间颜色和state相同 直接返回
return;
}
if(left <= tree[t].l && right >= tree[t].r){ //包含此区间
tree[t].init(state);
//更新第一类信息
return;
}
if(tree[t].state != -1){ //向下传递第二类信息
tree[L(t)].state
= tree[R(t)].state = tree[t].state;
tree[L(t)].init(tree[L(t)].state);
tree[R(t)].init(tree[R(t)].state);
}
int mid = tree[t].getMid();
if(right <= mid){
update(left, right, state, L(t));
}
else if(left > mid){
update(left, right, state, R(t));
}
else {
update(left, mid, state, L(t));
update(mid
+ 1, right, state, R(t));
}
if(tree[L(t)].state == 0 && tree[R(t)].state == 0){
tree[t].state
= 0;
}
else if(tree[L(t)].state == 1 && tree[R(t)].state == 1 ){
tree[t].state
= 1;
}
else {
tree[t].state
= -1;
}
//第一类信息的维护
tree[t].ll
= tree[L(t)].ll + (tree[L(t)].state == 0 ? tree[R(t)].ll : 0);
tree[t].rr
= tree[R(t)].rr + (tree[R(t)].state == 0 ? tree[L(t)].rr : 0);
tree[t].len
= max(tree[L(t)].len , max(tree[R(t)].len , tree[L(t)].rr + tree[R(t)].ll));
}

int checkIn(int a, int t){
if(tree[t].state == 0 && tree[t].len >= a){//如果当前区间长度满足 直接返回区间左端点
return tree[t].l;
}
if(tree[t].state == 1){//如果全部是满的,那就不要向下查询了,直接返回0
return 0;
}
if(tree[t].state == -1){ //分三种情况考虑 左边 中间 右边
if(tree[L(t)].len >= a){
return checkIn(a, L(t));
}
else if(tree[L(t)].rr + tree[R(t)].ll >= a){
return tree[t].getMid() - tree[L(t)].rr + 1;
}
else {
return checkIn(a, R(t));
}
}
return 0;
}

int main(){
scanf(
"%d%d",&N, &M);
int cmd, a, b;
bulid(
1, N, 1);
for(int i = 0; i < M; ++i){
scanf(
"%d",&cmd);
if(cmd == 1){
scanf(
"%d",&a);
int ans = checkIn(a, 1);
printf(
"%d\n",ans);
if(ans){
update(ans, ans
+ a - 1, 1, 1); //1进
}
}
else {
scanf(
"%d %d",&a, &b);
update(a, a
+ b - 1, 0, 1); //0 出
}
}

return 0;
}
posted @ 2011-04-07 20:33  L..  阅读(355)  评论(0编辑  收藏  举报