您的位置:首页 > 其它

poj3667 Hotel(成段更新+区间合并)

2016-05-11 22:04 344 查看
http://poj.org/problem?id=3667

题意:给你n个房间,m种操作,1操作为查看有没有连续长度为num的房间,若有,则返回其左端点,并将其置为非空;2操作为置空st~st+num-1区间内的房间。

思路:这题就是区间合并和成段更新的完美结合,然后加上懒惰标记的思想。麻烦就麻烦在对各变量的更新查询操作,以及要理解透彻几个变量的意义。ls代表从左数最长连续区间,rs代表从右数最长连续区间,ms代表区间内的最长连续区间。查询时分段查询,更新时按照区间合并的方法。好吧,我承认现在我不怎么会敲长代码。。

#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

typedef long long LL;

const int N = 50010;
const int INF = 1e8;

struct line
{
int l, r;
int ls, rs, ms;
int con;
}tree[4*N];

void build(int i, int l, int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].con = 0;//0表示全空,1表示全满
tree[i].ls = tree[i].rs = tree[i].ms = r-(l-1);
if(l == r)
{
return;
}
int mid = (l+r) >> 1;
build(i*2, l, mid);
build(i*2+1, mid+1, r);
}

int query(int i, int num)
{
if(tree[i].ls == num && (tree[i].r-tree[i].l+1) == num)
{
return tree[i].l;
}
if(tree[i].ms >= num)
{
if(tree[i].con != -1)
{
tree[i*2].con = tree[i*2+1].con = tree[i].con;
if(tree[i].con == 1)
{
tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = 0;
tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = 0;
}
else if(tree[i].con == 0)
{
tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = tree[i*2].r-tree[i*2].l+1;
tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = tree[i*2+1].r-tree[i*2+1].l+1;
}
tree[i].con = -1;
}
if(tree[i*2].ms >= num) return query(i*2, num);
if(tree[i*2].rs+tree[i*2+1].ls >= num) return tree[i*2].r-(tree[i*2].rs-1);
if(tree[i*2+1].ms >= num) return query(i*2+1, num);
}
return 0;
}

void update(int i, int l, int r, int flag)
{
if(tree[i].l == l && tree[i].r == r)
{
//flag为1表示置满,flag为0表示置空
if(flag == 1) tree[i].ls = tree[i].rs = tree[i].ms = 0;
else if(flag == 0) tree[i].ls = tree[i].rs = tree[i].ms = r-l+1;
tree[i].con = flag;
return;
}
if(tree[i].con != -1)
{
tree[i*2].con = tree[i*2+1].con = tree[i].con;
if(tree[i].con == 1)
{
tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = 0;
tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = 0;
}
else if(tree[i].con == 0)
{
tree[i*2].ls = tree[i*2].rs = tree[i*2].ms = tree[i*2].r-tree[i*2].l+1;
tree[i*2+1].ls = tree[i*2+1].rs = tree[i*2+1].ms = tree[i*2+1].r-tree[i*2+1].l+1;
}
tree[i].con = -1;
}
int mid = (tree[i].l+tree[i].r) >> 1;
if(mid >= r) update(i*2, l, r, flag);
else if(mid < l) update(i*2+1, l, r, flag);
else
{
update(i*2, l, mid, flag);
update(i*2+1, mid+1, r, flag);
}

if(tree[i*2].con == 0) tree[i].ls = tree[i*2].ms+tree[i*2+1].ls;
else tree[i].ls = tree[i*2].ls;

if(tree[i*2+1].con == 0) tree[i].rs = tree[i*2+1].ms+tree[i*2].rs;
else tree[i].rs = tree[i*2+1].rs;

tree[i].ms = max(max(tree[i*2].ms, tree[i*2+1].ms), tree[i*2].rs+tree[i*2+1].ls);
tree[i].ms = max(max(tree[i].ls, tree[i].rs), tree[i].ms);

if(tree[i].ms == tree[i].r-tree[i].l+1) tree[i].con = 0;
else if(tree[i].ms == 0) tree[i].con = 1;
else tree[i].con = -1;
}

int main()
{
// freopen("in.txt", "r", stdin);
int n, m, op, st, num;
scanf("%d%d", &n, &m);
build(1, 1, n);
while(m--)
{
scanf("%d", &op);
if(op == 1)
{
scanf("%d", &num);
st = query(1, num);
printf("%d\n", st);
if(st)
{
update(1, st, st+num-1, 1);
}
}
else if(op == 2)
{
scanf("%d%d", &st, &num);
update(1, st, st+num-1, 0);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj