CCF 202012-3 带配额的文件系统 练习

大模拟,没涉及什么算法主要是数据结构的设计、细节的考虑,挺锻炼的,记录一下,代码加了注释。

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <cctype>

using namespace std;
typedef long long ll;

struct file {
    bool isDir = true;
    map<string, file*> m;   // 子文件
    file* parent;           // 父文件
    string name;            // 文件名
    ll ld = -1, lr = -1;    // 配额
    ll rd, rr;              // 当前实际的额度, 普通文件时rd表示大小
};

file* root = new file();

// 根据指定分隔符进行分割字符串
vector<string> split(string s1, string seperator) {
    string s = s1.substr(1);
    vector<string> result;
    int posBegin = 0;
    int posSeperator = s.find(seperator);

    while (posSeperator != string::npos) {
        result.push_back(s.substr(posBegin, posSeperator - posBegin));//
        posBegin = posSeperator + seperator.size(); // 分隔符的下一个元素
        posSeperator = s.find(seperator, posBegin);
    }
    if (posBegin != s.length()) // 指向最后一个元素,加进来
        result.push_back(s.substr(posBegin));
    return result;
}

// 实际添加文件
bool addFile(file* f, string fileName, ll size) {
    if (f->rd + size > f->ld && f->ld != -1) return false;
    f->rd += size;
    file* t = f;
    vector<file*> fs;
    bool flag = true;
    while (t != nullptr) {
        t->rr += size;
        fs.push_back(t);
        if (t->rr > t->lr && t->lr != -1) {
            flag = false;
            break;
        }
        t = t->parent;
    }

    // 校验成功
    if (flag) {
        file* newFile = new file();
        newFile->rd = size;
        newFile->isDir = false;
        newFile->name = fileName;
        newFile->parent = f;
        f->m[fileName] = newFile;
        return true;
    }

    // 校验失败
    for (int i = 0; i < fs.size(); i ++) {
        if (i == 0) {
            fs[0]->rd -= size;
            fs[0]->rr -= size;
        } else {
            fs[i]->rr -= size;
        }
    }

    return false;
}

// 创建文件时还要额外创建目录
bool addPath(file* root, vector<string>& path, int index, ll size) {
    file* f = root;
    for (int i = index; i < path.size() - 1; i ++) {
        f->m[path[i]] = new file();
        f->m[path[i]]->parent = f;
        f = f->m[path[i]];
    }

    if (addFile(f, path[path.size() - 1], size)) {
        return true;
    } else {
        root->m.erase(path[index]); // 撤销
        return false;
    }
}

// 更新文件大小
bool updateFile(file* f, string name, ll size) {
    ll s = size - f->m[name]->rd;
    file* t = f; t->rd += s;
    if (t->rd > t->ld && t->ld != -1) {
        t->rd -= s;
        return false;
    }
    bool flag = true;
    vector<file*> fs;
    while (t != nullptr) {
        t->rr += s;
        fs.push_back(t);
        if (t->lr != -1 && t->lr < t->rr) {
            flag = false;
            break;
        }
        t = t->parent;
    }

    if (flag) {
        f->m[name]->rd = size;     // 实际更改文件大小
        return true;
    }

    // 校验失败 撤销
    for (int i = 0; i < fs.size(); i ++) {
        if (i == 0) {
            fs[0]->rd -= s;
            fs[0]->rr -= s;
        } else {
            fs[i]->rr -= s;
        }
    }

    return false;
}

// 检查创建普通文件
bool checkC(file* root, vector<string>& path, ll size, int index) {
    if (index == path.size() - 1) {
        if (!root->isDir) return false;

        if (root->m.count(path[index])) {   // 存在该文件
            if (root->m[path[index]]->isDir) return false;  // 最后要是普通文件
            file * f = root->m[path[index]];
            if (size > f->rd) {
                if (root->lr != - 1 && root->lr < root->rr + (size - f->rd)) return false;
                if (root->ld != - 1 && root->ld < root->rd + (size - f->rd)) return false;
            }

            return updateFile(root, path[index], size); // 更新
        }

        if (root->lr != - 1 && root->lr < root->rr + size) return false;
        if (root->ld != - 1 && root->ld < root->rd + size) return false;
        return addFile(root, path[index], size);
    }

    if (!root->isDir) return false; // 中间路径不是目录

    if (!root->m.count(path[index])) {
        return addPath(root, path, index, size);
    }

    return checkC(root->m[path[index]], path, size, index + 1);
}

// 删除
void remove(file* f, vector<string>& path, ll index) {
    if (!f->m.count(path[index])) return;   // 不存在返回

    if (!f->isDir) return;

    if (index == path.size() - 1 && f->m.count(path[index])) {
        ll size = f->m[path[index]]->isDir ? f->m[path[index]]->rr : f->m[path[index]]->rd; // 判断删除的是目录还是文件
        file* t = f;
        if (!f->m[path[index]]->isDir) t->rd -= size;
        f->m.erase(path[index]);
        while (t != nullptr) {
            t->rr -= size;
            t = t->parent;
        }
        return;
    }

    remove(f->m[path[index]], path, index + 1);
}

// 检查配额
bool checkQ(file* root, vector<string>& path, ll d, ll r, int index) {
    if (index == path.size() - 1) {
        if (!root->isDir) return false;

        if (root->m.count(path[index])) {
            file* f = root->m[path[index]];
            if (!f->isDir) return false;
            if (f->rd > d && d != 0) return false;
            if (f->rr > r && r != 0) return false;

            if (d != 0) f->ld = d;
            else f->ld = -1;
            if (r != 0) f->lr = r;
            else f->lr = -1;
            return true;
        }

        return false;
    }

    if (!root->m.count(path[index])) {
        return false;
    }

    if (!root->isDir) return false;

    return checkQ(root->m[path[index]], path, d, r, index + 1);
}

// 单独验证给根目录添加配额
bool checkRoot(file* root, ll d, ll r) {
    if (root->rd > d && d != 0) return false;
    if (root->rr > r && r != 0) return false;

    if (d != 0) root->ld = d;
    else root->ld = -1;
    if (r != 0) root->lr = r;
    else root->lr = -1;
    return true;
}

int main() {
    int n; cin >> n;
    string type;
    while (n --) {
        cin >> type;
        if (type == "C") {
            string path; ll size;
            cin >> path >> size;
            vector<string> p = split(path, "/");
            if (checkC(root, p, size, 0)) printf("Y\n");
            else printf("N\n");
        } else if (type == "R") {
            string path; cin >> path;
            vector<string> p = split(path, "/");
            remove(root, p, 0);
            printf("Y\n");
        } else if (type == "Q") {
            string path; ll ld, lr; cin >> path >> ld >> lr;
            vector<string> p = split(path, "/");
            if (p.empty()) {
                if (checkRoot(root, ld, lr)) printf("Y\n");
                else printf("N\n");
                continue;
            }

            if (checkQ(root, p, ld, lr, 0)) printf("Y\n");
            else printf("N\n");
        } else {
            printf("N\n");
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值