poj3667 hotel
这题目的解决方案关键是怎样制造连续的区域来判断是否符合要求。 你查找最大的区域时, 可以分为三个部分, 一个是左子树的最大连续区域, 一个是右子树最大区域, 一个 是左子树从右向左最大的连续区域加上右子树从左向右的最大区域
View Code
#include<stdio.h>
#include<string.h>
#include<math.h>
#define maxn 200008
struct node
{
int lval, rval, val;
int left, right;
int count;
void init(int x)
{
lval = rval = val = x * count;
}
}map[maxn];
inline int max(int x, int y)
{
return x > y? x:y;
}
void build(int left, int right, int side)
{
map[side].left = left;
map[side].right = right;
map[side].count = right - left + 1;
map[side].init(1);
if (left == right)
{
return;
}
int mid = (left + right) >> 1;
build(left, mid, side << 1);
build(mid + 1, right, side << 1 | 1);
return;
}
void update(int left, int right, int flag, int side)
{
int lchild, rchild;
lchild = side << 1;
rchild = side << 1 | 1;
if (map[side].left > right || map[side].right < left)
{
return;
}
if (left <= map[side].left && right >= map[side].right)
{
map[side].init(flag);
return;
}
if (map[side].val == map[side].count )
{
if (flag == 1)
{
return;
}
else
{
map[lchild].init(1);
map[rchild].init(1);
}
}
if (map[side].val == 0)
{
map[lchild].init(0);
map[rchild].init(0);
}
int mid = (map[side].left + map[side].right) >> 1;
if (mid >= right)
{
update(left, right, flag, lchild);
}
else if (left > mid )
{
update(left, right, flag, rchild);
}
else
{
update(left, mid, flag, lchild);
update(mid + 1, right, flag, rchild);
}
// left
map[side].lval = map[rchild].lval + (map[rchild].val == map[rchild].count ? map[lchild].lval:0);
// right
map[side].rval = map[lchild].rval + (map[lchild].val == map[lchild].count? map[rchild].rval:0);
//current
map[side].val = max(map[lchild].lval+map[rchild].rval, max(map[lchild].val, map[rchild].val));
return ;
}
int find(int val, int side)
{
if (map[side].val < val)
{
return 0;
}
if (map[side].val == map[side].count)
{
return map[side].left;
}
if (map[side].rval >= val)
{
return map[side].left;
}
if (map[side << 1].val >= val)
{
return find(val, side << 1);
}
if (map[side << 1].lval + map[side << 1 | 1].rval >= val)
{
return map[side << 1].right - map[side << 1].lval + 1;
}
return find(val, side << 1 | 1);
}
void print(int m)
{
int choice, x, y;
for (int i = 0; i < m; i ++)
{
scanf("%d", &choice);
if (choice == 1)
{
scanf("%d", &x);
choice = find(x, 1);
printf("%d\n", choice);
if (choice > 0)
{
update(choice, choice + x - 1, 0, 1);
}
}
else
{
scanf("%d%d", &x, &y);
update(x, x + y - 1, 1, 1);
}
}
return ;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
build(1, n, 1);
print(m);
return 0;
}