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;
}