您的位置:首页 > 其它

codeforces 46D Parking Lot(线段树模拟区间管理 or set模拟)

2015-08-28 01:47 337 查看
题意:

可以看成是 poj Hotel 那道题的加强版。

这里是找车位,还要考虑与前后车之间的距离。。

不过这里n只有100,用set,就成了水题啊。。。

思路:

1) 线段树

比起 Hotel 也就是多讨论几种情况吧。。

const int N = 100000 + 5;

struct Node {
int len, l, r, m, tag; // 0 - no tag, 1 - free, 2 - occupied

void upd(int x) {
if ( x == 1 ) {
l = r = m = len;
}
if ( x == 2 ) {
l = r = m = 0;
}
tag = x;
}
};

Node tr[N<<2];
int qL, qR;
#define lc o<<1
#define rc o<<1|1

void push_down(int o) {
if ( tr[o].tag ) {
tr[lc].upd(tr[o].tag);
tr[rc].upd(tr[o].tag);
tr[o].tag = 0;
}
}

void push_up(int o) {
tr[o].l = tr[lc].l;
if ( tr[lc].l == tr[lc].len ) tr[o].l += tr[rc].l;

tr[o].r = tr[rc].r;
if ( tr[rc].r == tr[rc].len ) tr[o].r += tr[lc].r;

tr[o].m = tr[lc].r + tr[rc].l;
tr[o].m = max ( tr[o].m, max ( tr[lc].m, tr[rc].m ) );
}

int query(int o, int l, int r) {
if ( tr[o].m < qL ) return -1;
if ( l == r ) return l; // take care...
int m = (l + r) >> 1, ret;
push_down(o);
if ( tr[lc].m >= qL )
ret = query(lc, l, m);
else if ( tr[lc].r + tr[rc].l >= qL ) {
ret = m - tr[lc].r + 1;
} else {
ret = query(rc, m+1, r);
}
push_up(o);
return ret;
}

void update(int o, int l, int r, int x) {
if ( qL <= l && r <= qR ) {
tr[o].upd(x);
//cout << " upd: " << l << ' ' << r << " : " << tr[o].l << ' ' << tr[o].r << ' ' << tr[o].m << endl;
return;
}
int m = (l + r) >> 1;
push_down(o);
if ( qL <= m )
update(lc, l, m, x);
if ( qR > m )
update(rc, m+1, r, x);
push_up(o);
//cout << " upd: " << l << ' ' << r << " : " << tr[o].l << ' ' << tr[o].r << ' ' << tr[o].m << endl;
}

void build(int o, int l, int r) {
int len = r - l + 1;
tr[o] = (Node) {len, len, len, len, 0};
if ( l != r ) {
int m = (l + r) >> 1;
build(lc, l, m); build(rc, m+1, r);
}
}

int rec
[2], L, b, f, n;

int search_space(int i, int car) {
int id;

if ( tr[1].m == L ) { // no car
qL = car;
id = query(1, 1, L);
if ( id != -1 ) {
rec[i][0] = id, rec[i][1] = id + car - 1;
return id - 1;
}
}

qL = car + f;
if ( tr[1].l >= qL ) {
id = 1;
rec[i][0] = id, rec[i][1] = id + car - 1;
return id - 1;
}

qL = car + b + f;
id = query(1, 1, L);
if ( id != -1 ) {
id += b;
rec[i][0] = id, rec[i][1] = id + car - 1;
return id - 1;
}

qL = car + b;
if ( tr[1].r >= qL ) {
id = L - tr[1].r + b + 1;
rec[i][0] = id, rec[i][1] = id + car - 1;
return id - 1;
}

return -1;
}

int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int x, y;
scanf("%d%d%d%d", &L, &b, &f, &n);
memset(rec, -1, sizeof(rec));
build(1, 1, L);
rep(i, 1, n) {
scanf("%d%d", &x, &y);
if ( x == 1 ) {
int res = search_space(i, y);
if ( res != -1 ) {
qL = rec[i][0], qR = rec[i][1];
update(1, 1, L, 2);
}
printf("%d\n", res);
} else {
qL = rec[y][0], qR = rec[y][1];
update(1, 1, L, 1);
}
}
return 0;
}


2)set模拟

set 维护车占的区间前后端点。

有个小技巧, 虚拟一个 -b 和 L + f 端点,情况就统一了。。

const int N = 100000 + 5;
int rec
[2], L, b, f, n;
set<int> s;
set<int>::iterator fir, sec;

int search_space(int i, int car) {
int len = car + b + f;
for(fir = s.begin(); fir != s.end(); ++ fir) {
sec = fir; ++ sec;
if ( sec != s.end() && *sec - *fir >= len ) {
int st = *fir + b;
int ed = st + car;
s.insert(st);
s.insert(ed);
rec[i][0] = st;
rec[i][1] = ed;
return st;
}
++ fir;
}
return -1;
}

int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int x, y;
scanf("%d%d%d%d", &L, &b, &f, &n);
memset(rec, -1, sizeof(rec));
s.insert(-b); s.insert(L + f);
rep(i, 1, n) {
scanf("%d%d", &x, &y);
if ( x == 1 ) {
int res = search_space(i, y);
printf("%d\n", res);
} else {
s.erase(rec[y][0]);
s.erase(rec[y][1]);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: