HDU_2871

    胡浩的博客上说这个可以做splay的热身题,结果写出来洋洋洒洒270行代码却落得TLE收场,不得不改成线段树去写了。

    reset操作是最简单的,直接将根初始化并加个延迟标记即可。

    我们可以用lc[](left contiguous)表示一个区间从左边开始连续有多少个空位,rc[](right contiguous)表示一个区间从右边开始连续有多少个空位,mc(max contiguous)表示这个区间内最长的连续的空位。有了这三个数组我们就可以很方便地实现New操作了。

    对于Free操作,知道这个点是否是空位是很简单的,但为了获得Memory unit的左、右端点,我们可以额外加两个数组lu[](left unit)、ru[right unit]表示左右端点。这样Free操作的查询功能就实现了,而实现Free删除的功能就可以选择直接对将该段进行染色,染成0即可。

    对于Get操作,我们再额外加一个数组tree[]表示当前这个区间一共有多少个Memory units,但是我们只将每个Memory units左端的unit的tree[]值赋为1,这样就实现了计数的功能,同时查找起来也比较方便,找到的最后一个位置就是该Memory units的左端点。

#include<stdio.h>
#include<string.h>
#define MAXD 50010
int N, M, tree[4 * MAXD], to[4 * MAXD], mc[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], lu[4 * MAXD], ru[4 * MAXD];
int getmax(int x, int y)
{
return x > y ? x : y;
}
void update(int cur, int x, int y)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
mc[cur] = getmax(mc[ls], mc[rs]);
mc[cur] = getmax(mc[cur], rc[ls] + lc[rs]);
lc[cur] = lc[ls] + (lc[ls] == mid - x + 1 ? lc[rs] : 0);
rc[cur] = rc[rs] + (rc[rs] == y - mid ? rc[ls] : 0);
tree[cur] = tree[ls] + tree[rs];
}
void pushdown(int cur, int x, int y)
{
if(to[cur] != -1)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
to[ls] = to[rs] = to[cur];
tree[ls] = tree[rs] = 0;
mc[ls] = lc[ls] = rc[ls] = (to[cur] ? 0 : mid - x + 1);
mc[rs] = lc[rs] = rc[rs] = (to[cur] ? 0 : y - mid);
if(to[cur])
lu[ls] = lu[rs] = lu[cur], ru[ls] = ru[rs] = ru[cur];
to[cur] = -1;
}
}
void build(int cur, int x, int y)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
to[cur] = -1, tree[cur] = 0;
mc[cur] = lc[cur] = rc[cur] = y - x + 1;
if(x == y)
return ;
build(ls, x, mid);
build(rs, mid + 1, y);
}
int Searchlen(int cur, int x, int y, int len)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x == y)
return x;
pushdown(cur, x, y);
if(mc[ls] >= len)
return Searchlen(ls, x, mid, len);
else if(rc[ls] + lc[rs] >= len)
return mid - rc[ls] + 1;
else
return Searchlen(rs, mid + 1, y, len);
}
void color(int cur, int x, int y, int s, int t, int c)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x >= s && y <= t)
{
to[cur] = c;
tree[cur] = 0;
mc[cur] = lc[cur] = rc[cur] = (c ? 0 : y - x + 1);
if(c)
{
lu[cur] = s, ru[cur] = t;
if(x == s)
{
if(x != y)
{
pushdown(cur, x, y);
color(ls, x, mid, s, t, c);
update(cur, x, y);
}
else
tree[cur] = 1;
}
}
return ;
}
pushdown(cur, x, y);
if(mid >= s)
color(ls, x, mid, s, t, c);
if(mid + 1 <= t)
color(rs, mid + 1, y, s, t, c);
update(cur, x, y);
}
int Search(int cur, int x, int y, int goal, int &l, int &r)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x == y)
{
if(mc[cur] == 0)
{
l = lu[cur], r = ru[cur];
return 1;
}
return 0;
}
pushdown(cur, x, y);
if(goal <= mid)
return Search(ls, x, mid, goal, l, r);
else
return Search(rs, mid + 1, y, goal, l, r);
}
void reset()
{
to[1] = tree[1] = 0;
mc[1] = lc[1] = rc[1] = N;
printf("Reset Now\n");
}
void newunit(int len)
{
int x;
x = Searchlen(1, 1, N, len);
printf("New at %d\n", x);
color(1, 1, N, x, x + len - 1, 1);
}
void free(int x)
{
int l, r;
if(Search(1, 1, N, x, l, r))
{
printf("Free from %d to %d\n", l, r);
color(1, 1, N, l, r, 0);
}
else
printf("Reject Free\n");
}
int getunit(int cur, int x, int y, int k)
{
int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1;
if(x == y)
return lu[cur];
pushdown(cur, x, y);
if(k <= tree[ls])
return getunit(ls, x, mid, k);
else
return getunit(rs, mid + 1, y, k - tree[ls]);
}
void solve()
{
int i, j, k, x;
char b[10];
for(i = 0; i < M; i ++)
{
scanf("%s", b);
if(b[0] == 'R')
reset();
else if(b[0] == 'N')
{
scanf("%d", &x);
if(mc[1] < x)
printf("Reject New\n");
else
newunit(x);
}
else if(b[0] == 'F')
{
scanf("%d", &x);
free(x);
}
else
{
scanf("%d", &k);
if(tree[1] < k)
printf("Reject Get\n");
else
printf("Get at %d\n", getunit(1, 1, N, k));
}
}
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
build(1, 1, N);
solve();
printf("\n");
}
return 0;
}


posted on 2012-03-31 02:29  Staginner  阅读(676)  评论(0编辑  收藏  举报