題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2871
代碼風格:http://www.notonlysuccess.com/index.php/segment-tree-complete/
題目大意:一段內存條,new k表示要要申請k個位置的空內存,free k表示要釋放第k個位置的內存及與k位置內存相關的內存,get k表示要獲得從內存條左到右第k段內存輸出左端點,reset表示釋放整段內存
算法:線段樹,STL(vector)
思路:new覆蓋有空的位置,並記錄下申請到內存的左邊位置和右邊位置
free時,找到那個內存位置的左端點和右端點,並且取消覆蓋
get k時,如果v.size() < k,輸出reject ,否則直接輸出左端點v[k-1].l
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 |1
#define mid int m = (l + r) >> 1
struct Seg
{
int l, r;
}p;
const int Max = 50010;
int lsum[Max << 2], rsum[Max << 2], msum[Max << 2], cover[Max << 2];
vector<Seg> v;
vector<Seg>::iterator it;
int maxz(int a, int b)
{
return a > b? a : b;
}
void PushUp(int rt, int m)
{
lsum[rt] = lsum[rt << 1];
rsum[rt] = rsum[rt << 1 | 1];
if(lsum[rt] == m - (m >> 1))
lsum[rt] += lsum[rt << 1 | 1];
if(rsum[rt] == m >> 1)
rsum[rt] += rsum[rt << 1];
msum[rt] = maxz(maxz(msum[rt << 1], msum[rt << 1 | 1]), lsum[rt << 1 | 1] + rsum[rt << 1]);
}
void PushDown(int rt, int m)
{
if(cover[rt] != -1)
{
cover[rt << 1] = cover[rt << 1 | 1] = cover[rt];
msum[rt << 1] = lsum[rt << 1] = rsum[rt << 1] = cover[rt] ? 0 : m - (m >> 1);
msum[rt << 1 | 1] = lsum[rt << 1 | 1] = rsum[rt << 1 | 1] = cover[rt] ? 0 : m >> 1;
cover[rt] = -1;
}
}
void build(int l, int r, int rt)
{
if(l == r)
{
msum[rt] = rsum[rt] = lsum[rt] = 1;
return ;
}
mid ;
build(lson);
build(rson);
PushUp(rt, r-l+1);
}
void update(int L, int R, int k, int l, int r, int rt)
{
if(L <= l && r <= R)
{
cover[rt] = k;
msum[rt] = rsum[rt] = lsum[rt] = k ? 0 : r-l+1;
return ;
}
mid ;
PushDown(rt, r-l+1);
if(L <= m)
update(L, R, k, lson);
if(m < R)
update(L, R, k, rson);
PushUp(rt, r-l+1);
}
int query(int k, int l, int r, int rt)
{
if(l == r)
{
return l;
}
mid ;
PushDown(rt, r-l+1);
if(k <= msum[rt << 1])
return query(k, lson);
else if(k <= lsum[rt << 1 | 1] + rsum[rt << 1])
return m - rsum[rt << 1] + 1;
else
return query(k, rson);
}
bool cmp(const Seg &a, const Seg &b)
{
return a.l < b.l ;
}
int main()
{
int n, m;
char op[15];
int a;
while(scanf("%d%d", &n, &m) != EOF)
{
build(1, n, 1);
v.clear();
memset(cover, -1, sizeof(cover));
while(m --)
{
scanf("%s", op);
if(op[0] == 'R')
{
update(1, n, 0, 1, n, 1);
v.clear();
printf("Reset Now\n");
}
else if(op[0] == 'N')
{
scanf("%d", &a);
if(msum[1] < a)
{
printf("Reject New\n");
}
else
{
int k = query(a, 1, n, 1);
printf("New at %d\n", k);
p.l = k;
p.r = k+a-1;
update(p.l, p.r, 1, 1, n, 1);
it = upper_bound(v.begin(), v.end(), p, cmp);
v.insert(it, p);
}
}
else if(op[0] == 'F')
{
scanf("%d", &a);
p.l = a; p.r = a;
it = upper_bound(v.begin(), v.end(), p, cmp);
int temp = it - v.begin() - 1;
if(temp == -1 || v[temp].r < a)
{
printf("Reject Free\n");
}
else
{
update(v[temp].l, v[temp].r, 0, 1, n, 1);
printf("Free from %d to %d\n", v[temp].l, v[temp].r);
v.erase(v.begin()+temp);
}
}
else
{
scanf("%d", &a);
if(v.size() < a)
{
printf("Reject Get\n");
}
else
{
printf("Get at %d\n", v[a-1].l);
}
}
}
printf("\n");
}
return 0;
}