萌新求助嘿~~ 简单模拟我都不会qwq

CF7B Memory Manager

leprechaun_kdl @ 2019-11-05 00:43:27

  • 在第#42个点WA了呢qwq

我把我的代码大概写了下注释在里面 , (怕您们不好理解呢)

我感觉思路没什么问题,但不知道哪里细节还有问题。

希望dalao指出.. .期待ing

我是用ODT (珂朵莉树) 实现的讷

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
#define ri register int

//这个是ODT树呢。。
//l,r是这个区间的左右边界,当然都是闭区间
//val是这个区间对应的编号,len是区间的长度
struct ODT
{
    int l, r;
    mutable int val, len;
    ODT(int L = -1, int R = -1, int V = 0, int E = 0)
    : l(L), r(R), val(V), len(E) {}
    bool operator< (const ODT& x) const
    { return l < x.l;}
};
typedef set<ODT>::iterator IT;

//n,m 如题意;xth是第x个请求成功的内存编号,当然一开始是1啦。。
set<ODT> nc;
int n, m, xth = 1;
char s[13];

//这是尝试申请内存
inline void add_nc(int le)
{
    int flag = 1;
    IT it = nc.begin();
        //找第一个可用的(0)且长度大于等于所需的内存
        //并将这段0区间分为两端
    for ( ; it != nc.end(); ++it)
    {
        if (it->val != 0) continue;
        if (it->len >= le)
        {
            int L = it->l, R = it->r, LE = it->len;
            int pos = L + le;
            nc.erase(it);
            nc.insert(ODT(L, pos-1, xth, le));
            if (pos <= R) nc.insert(ODT(pos, R, 0, LE-le));
            flag = 0;
            break;
        }
    }
        //如果没找到输出NULL,否则输出编号
    if (flag) printf("NULL\n");
    else printf("%d\n", xth), ++xth;
}

//这是删除编号为x的内存
inline void erase_nc(int x)
{
    int flag = 1;
    IT it = nc.begin();
        //寻找这段内存并赋值为零
        //(本来可以直接改变找到区间的val为0滴,但不知道为什么比删除后重新加入要慢qwq)
    for ( ; it != nc.end(); ++it)
    {
        if (it->val == x)
        {
            int L = it->l, R = it->r, LE = it->len;
            nc.erase(it);
            it = nc.insert(ODT(L, R, 0, LE)).first;
            flag = 0;
            break;
        }
    }
        //如果不存在编号输出ILLEGAL_ERASE_ARGUMENT
        //否则查看左右相邻区间val是否为0,并将其合并
    if (flag) printf("ILLEGAL_ERASE_ARGUMENT\n");
    else
    {
        if (it != nc.begin())
        {
            IT itn = it;
            --it;
            if (it->val == 0)
            {
                int L = it->l, R = itn->r, LE = it->len;
                LE += itn->len;
                nc.erase(it), nc.erase(itn);
                itn = nc.insert(ODT(L, R, 0, LE)).first;
            }
            it = itn;
        }
        IT itn = it;
        ++it;
        if (it != nc.end() && it->val == 0)
        {
            int L = itn->l, R = it->r, LE = it->len;
            LE += itn->len;
            nc.erase(it), nc.erase(itn);
            nc.insert(ODT(L, R, 0, LE));
        }
    }
}

//这是前移操作
inline void defragment()
{
    int LEO = 0;
    IT it = nc.begin();
        //将0区间删除,并累加其长度。
        //将非0区间向前移动已经删除的0区间长度之和
    for ( ; it != nc.end(); )
    {
        if(it->val == 0)
        {
            LEO += it->len;
            IT itn = it;
            ++itn;
            nc.erase(it);
            it = itn;
        } else {
            int L = it->l, R = it->r, V = it->val, LE = it->len;
            L -= LEO, R -= LEO;
            nc.erase(it);
            it = nc.insert(ODT(L, R, V, LE)).first;
            ++it;
        }
    }
    //最后如果还有0区间,将0区间加在最后面
    if(LEO) nc.insert(ODT(m-LEO+1, m, 0, LEO));
}

signed main()
{
    scanf("%d%d", &n, &m);
        //最开始都是0,即全部可使用
    nc.insert(ODT(1, m, 0, m));
    for (ri i = 1; i <= n; ++i)
    {
        //靠第一个字母就可以区分了讷。。
        scanf("%s", s);
        if (s[0] == 'a')
        {
            int x;
            scanf("%d", &x);
            add_nc(x);
        } else if (s[0] == 'e') {
            int x;
            scanf("%d", &x);
            erase_nc(x);
        } else if (s[0] == 'd') {
            defragment();
        }
    }
    return 0;
}

by Rbu_nas @ 2019-11-05 07:13:13

感觉没啥毛病,有的地方我也不太清楚那样写对不对..


by leprechaun_kdl @ 2019-11-05 08:39:30

QAQ

by leprechaun_kdl @ 2020-01-20 23:14:58

@Rem°

非常谢谢您当时愿意为我看这道题。

这是我退役以后看的第一道题,我对着CodeForces上的数据把它A了。

重点在它一开始就erase一个数,而且恰好是我规定的无内存状态。所以会把最开始的那总区间减去。

所以只要在erase前特判缩减的数是否小于等于0,如果小于等于0,就直接输出。

这是AC代码,只在原基础上加了一个if(在125行)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
#define ri register int

struct ODT
{
    int l, r;
    mutable int val, len;
    ODT(int L = -1, int R = -1, int V = 0, int E = 0)
    : l(L), r(R), val(V), len(E) {}
    bool operator< (const ODT& x) const
    { return l < x.l;}
};
typedef set<ODT>::iterator IT;
set<ODT> nc;
int n, m, xth = 1;
char s[13];

inline void add_nc(int le)
{
    int flag = 1;
    IT it = nc.begin();
    for ( ; it != nc.end(); ++it)
    {
        if (it->val != 0) continue;
        if (it->len >= le)
        {
            int L = it->l, R = it->r, LE = it->len;
            int pos = L + le;
            nc.erase(it);
            nc.insert(ODT(L, pos-1, xth, le));
            if (pos <= R) nc.insert(ODT(pos, R, 0, LE-le));
            flag = 0;
            break;
        }
    }
    if (flag) printf("NULL\n");
    else printf("%d\n", xth), ++xth;
}

inline void erase_nc(int x)
{
    int flag = 1;
    IT it = nc.begin();
    for ( ; it != nc.end(); ++it)
    {
        if (it->val == x)
        {
            it->val = 0;
            flag = 0;
            break;
        }
    }
    if (flag) printf("ILLEGAL_ERASE_ARGUMENT\n");
    else
    {
        if (it != nc.begin())
        {
            IT itn = it;
            --it;
            if (it->val == 0)
            {
                int L = it->l, R = itn->r, LE = it->len;
                LE += itn->len;
                nc.erase(it), nc.erase(itn);
                itn = nc.insert(ODT(L, R, 0, LE)).first;
            }
            it = itn;
        }
        IT itn = it;
        ++it;
        if (it != nc.end() && it->val == 0)
        {
            int L = itn->l, R = it->r, LE = it->len;
            LE += itn->len;
            nc.erase(it), nc.erase(itn);
            nc.insert(ODT(L, R, 0, LE));
        }
    }
}

inline void defragment()
{
    int LEO = 0;
    IT it = nc.begin();
    for ( ; it != nc.end(); )
    {
        if(it->val == 0)
        {
            LEO += it->len;
            IT itn = it;
            ++itn;
            nc.erase(it);
            it = itn;
        } else {
            int L = it->l, R = it->r, V = it->val, LE = it->len;
            L -= LEO, R -= LEO;
            nc.erase(it);
            it = nc.insert(ODT(L, R, V, LE)).first;
            ++it;
        }
    }
    if(LEO) nc.insert(ODT(m-LEO+1, m, 0, LEO));
}

signed main()
{
    scanf("%d%d", &n, &m);
    nc.insert(ODT(1, m, 0, m));
    for (ri i = 1; i <= n; ++i)
    {
        scanf("%s", s);
        if (s[0] == 'a')
        {
            int x;
            scanf("%d", &x);
            add_nc(x);
        } else if (s[0] == 'e') {
            int x;
            scanf("%d", &x);
            if (x <= 0) {
                printf("ILLEGAL_ERASE_ARGUMENT\n");
                continue;
            }
            erase_nc(x);
        } else if (s[0] == 'd') {
            defragment();
        }
    }
    return 0;
}

|