题目链接:http://poj.org/problem?id=3667
题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间
#include <iostream>
#include <cstdio>
#define lson l, m, x<<1
#define rson m+1, r, x<<1|1
using namespace std;
const int INF = (1<<31)-1;
const int maxn = 55555;
int lsum[maxn<<2], rsum[maxn<<2], sum[maxn<<2];
int cover[maxn<<2];
void pushUp(int x, int m)
{
sum[x] = max(sum[x<<1], sum[x<<1|1]);
sum[x] = max(sum[x], rsum[x<<1] + lsum[x<<1|1]);
lsum[x] = lsum[x<<1];
rsum[x] = rsum[x<<1|1];
if (lsum[x] == (m-(m>>1)))
lsum[x] += lsum[x<<1|1];
if (rsum[x] == (m>>1))
rsum[x] += rsum[x<<1];
}
void pushDown(int x, int m)
{
if (cover[x] != -1)
{
int lpos = x<<1;
int rpos = x<<1|1;
cover[lpos] = cover[rpos] = cover[x];
sum[lpos] = lsum[lpos] = rsum[lpos] = cover[x] ? 0 : (m-(m>>1));
sum[rpos] = lsum[rpos] = rsum[rpos] = cover[x] ? 0 : (m>>1);
cover[x] = -1;
}
}
void build(int l, int r, int x)
{
sum[x] = lsum[x] = rsum[x] = r-l+1;
cover[x] = -1;
if (l == r)
{
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
}
void update(int l, int r, int x, int L, int R, int C)
{
if (L <= l && r <= R)
{
sum[x] = lsum[x] = rsum[x] = (r-l+1)*(1-C);
cover[x] = C;
return ;
}
pushDown(x, r-l+1);
int m = (l+r) >> 1;
if (L <= m) update(lson, L, R, C);
if (R > m) update(rson, L, R, C);
pushUp(x, r-l+1);
}
int query(int l, int r, int x, int a)
{
if (l == r)
{
return l;
}
pushDown(x, r-l+1);
int m = (l+r) >> 1;
if (sum[x<<1] >= a)
return query(lson, a);
else if (rsum[x<<1] + lsum[x<<1|1] >= a)
return m - rsum[x<<1] + 1;
else
return query(rson, a);
}
int main()
{
int n, m;
scanf("%d%d", &n,&m);
build(1, n, 1);
while (m > 0)
{
m--;
int op, a, b;
scanf("%d", &op);
if (op == 1)
{
scanf("%d", &a);
if (sum[1] < a)
puts("0");
else
{
int p = query(1, n, 1, a);
printf("%d\n", p);
update(1, n, 1, p, p+a-1, 1);
}
}
else
{
scanf("%d%d", &a, &b);
update(1, n, 1, a, a+b-1, 0);
}
}
return 0;
}
本文介绍了一种使用线段树解决区间更新与查询最长空闲段的问题,通过覆盖标记减少更新操作复杂度,利用左右子树信息合并提高查询效率。
679

被折叠的 条评论
为什么被折叠?



