HDU 2871 Memory Control(线段树区间合并+二分)

题意:

模拟一个内存分配机制。
Reset:重置,释放所有空间
New x:申请内存为x的空间,输出左地址
Free x:释放地址x所在的内存块
Get x:查询第x个内存块,输出左地址

解析:

可以用一个vector来记录所有的内存块的区间。
New x操作可以利用如同 POJ3667 中的query操作查找到最右边的位置。然后把找到的区间二分插入,vector中。
Free x操作,由于每个内存块的区间都是互不相交的,所以可以二分找到离x最近的开始位置,释放该内存块。
Get x操作就直接输出第x个内存块的开始地址。
Reset操作可以直接利用 modify 更新,而不要重新 build ,这样会更快。

my code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
#define LEN(L, R) ((R) - (L) + 1)
#define MID (L + R) >> 1
#define pb push_back
using namespace std;
const int N = 50010;
struct Segment { int st, en; };

int n, m;
vector<Segment> list;

int mxL[N<<2], mxR[N<<2], mx[N<<2];
int cov[N<<2];

int max(int a, int b, int c) {
    return max(a, max(b, c));
}

inline void maintain (int o, int L, int R, int val) {
    cov[o] = val;
    mxL[o] = mxR[o] = mx[o] = (val ? 0 : LEN(L, R));
}

inline void pushUp (int o, int L, int R) {
    int M = MID;
    mx[o] = max(mx[ls], mx[rs], mxL[rs] + mxR[ls]);
    mxL[o] = mxL[ls] + (mxL[ls] == LEN(L, M) ? mxL[rs] : 0);
    mxR[o] = mxR[rs] + (mxR[rs] == LEN(M+1, R) ? mxR[ls] : 0);
}

inline void pushDown (int o, int L, int R) {
    if (cov[o] != -1) {
        int M = MID;
        maintain(lson, cov[o]);
        maintain(rson, cov[o]);
        cov[o] = -1;
    }
}

void build (int o, int L, int R) {
    cov[o] = -1;
    if (L == R) {
        maintain(o, L, R, 0);
        return;
    }
    int M = MID;
    build(lson);
    build(rson);
    pushUp(o, L, R);
}

void modify(int o, int L, int R, int ql, int qr, int val) {
    if(ql <= L && R <= qr) {
        maintain(o, L, R, val);
        return ;
    }
    int M = MID;
    pushDown(o, L, R);
    if(ql <= M) modify(lson, ql, qr, val);
    if(qr > M) modify(rson, ql, qr, val);
    pushUp(o, L, R);
}

int query(int o, int L, int R, int need) {
    if(L == R) return L;
    int M = MID, ret = 0;
    pushDown(o, L, R);
    if(mx[ls] >= need) ret = query(lson, need);
    else if(mxR[ls] + mxL[rs] >= need)
        ret = M - mxR[ls] + 1;
    else ret = query(rson, need);
    pushUp(o, L, R);
    return ret;
}

int search(int x) {
    int L = 0, R = list.size()-1;
    while(L <= R) {
        int M = MID;
        int tmp = list[M].st;
        if(tmp <= x) L = M + 1;
        else R = M - 1;
    }
    return L;
}

void New(int x) {
    if(mx[1] < x) puts("Reject New");
    else {
        int ql = query(1, 1, n, x);
        int qr = ql + x - 1;
        int pos = search(ql);
        list.insert(list.begin()+pos, (Segment){ql, qr});
        modify(1, 1, n, ql, qr, 1);
        printf("New at %d\n", ql);
    }
}

void Free(int x) {
    int pos = search(x) - 1;
    if(pos < 0 || list[pos].en < x) {
        puts("Reject Free");
    }else {
        int ql = list[pos].st, qr = list[pos].en;
        printf("Free from %d to %d\n", ql, qr);
        modify(1, 1, n, ql, qr, 0);
        list.erase(list.begin() + pos, list.begin() + pos + 1);
    }
}

void Get(int x) {
    if(x > list.size()) {
        puts("Reject Get");
    }else {
        printf("Get at %d\n", list[x-1].st);
    }
}

int main () {
    char op[5];
    int x;

    while (scanf("%d%d", &n, &m) == 2) {
        build (1, 1, n);
        list.clear();
        char op[5];
        while (m--) {
            scanf("%s", op);
            if(op[0] == 'N') {
                scanf("%d", &x);
                New(x);
            }else if(op[0] == 'F') {
                scanf("%d", &x);
                Free(x);
            }else if(op[0] == 'G') {
                scanf("%d", &x);
                Get(x);
            }else if(op[0] == 'R') {
                modify(1, 1, n, 1, n, 0);
                list.clear();
                puts("Reset Now");
            }       
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(HDU,2871)