ccf 202012-3 带配额的文件系统

ccf没调试太狗血了

只过了题目里给的两个测试用例,不知道哪里错了,需要自己构造测试用例嘛🤒

ps: 花了好几天时间写的,改天再看吧

//
// Created by clay on 2021/4/24.
//

#include <bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin>>n;
    cin.get();
    map<string,map<string,int>> mp;//保存所有的孩子结点 (考虑其对总配额的影响) //文件的大小不可能为0
    map<string,int> mpY; //保存当前路径为目录还是文件(1是目录,2是文件,0是未分配)
    map<string,map<int,int>> mp1,mp2;  //0和1是子、后代配额,2和3是实际的子、后代配额
    mpY["/"]=1; //根目录肯定是目录
    auto create=[&](string t,int i)->bool {
        //对所有的前序结点的后代配额值进行检查(除掉最后一个目录<文件正好处于的目录>)
        int pos=t.find_last_of('/');
        string folder=t.substr(0,pos);
        string file=t.substr(pos+1);
        int diff=i;
        if(mpY[t]==1)
            return false;
        if(mp[folder][file]>0)
            diff=i-mp[folder][file];  //可能原来就存在了,只是在原来的基础上进行修改
        //对根目录的配额进行判断
        if(pos!=0&&mp1["/"][1]!=0&&i>mp1["/"][1]-mp1["/"][3]) //对根目录"/"处理,防止其是唯一目录
            return false;
        if(pos==0){  //仅含根目录的配额判断
            if(mp1["/"][1]!=0&&i>mp1["/"][1]-mp1["/"][3])
                return false;
            if(mp1["/"][0]!=0&&i>mp1["/"][0]-mp1["/"][2])
                return false;
            mp1["/"][3]+=diff;
            mp1["/"][2]+=diff;
            return true;
        }
        int p=1;  //第一个符号肯定是'/'
        mp2=mp1;
        while((p=t.find('/',p))!=pos){
            string s=t.substr(0,p);
            if(mpY[s]==2){
                mp1=mp2;
                return false; //如果当前路径为文件,则返回错误
            }
            if(mp1[s][1]!=0&&i>mp1[s][1]-mp1[s][3]) { //配额方面筛选
                mp1=mp2;
                return false;
            }
            mpY[s]=1;
            mp1[s][3]+=diff; //否则就将其配额值进行增加
            p++;
        }
        if(mpY[folder]==2){
            mp1=mp2;
            return false; //如果当前路径为文件,则返回错误
        }
        //分割出目录的那一部分
        if(mp1[folder][0]!=0&&i>mp1[folder][0]-mp1[folder][2]){
            mp1=mp2;
            return false; //如果当前路径为文件,则返回错误
        }
        if(mp1[folder][1]!=0&&i>mp1[folder][1]-mp1[folder][3]) { //配额方面筛选
            mp1=mp2;
            return false;
        }

        //这时根目录的配额才可以加上
        mp1["/"][3]+=diff;  //注意这里不是i!

        mpY[folder]=1;
        mp1[folder][2]+=i;
        mp1[folder][3]+=i;
        mp[folder][file]=i; //进行配额
        mpY[t]=2;
        return true;
    };
    auto remove=[&](string t)->bool {
        //判断是否为文件
        if(mpY[t]==2){  //说明其肯定是存在的
            mpY[t]=0;
            int pos=t.find_last_of('/');
            string folder=t.substr(0,pos);
            string file=t.substr(pos+1);
            mp1["/"][3]-=mp[folder][file];
            int p=1;  //对所有的父文件配额进行修改
            while((p=t.find('/',p))!=pos&&p!=-1){
                string s=t.substr(0,p);
                mp1[s][3]-=mp[folder][file]; //否则就将其配额值进行增加
                p++;
            }
            mp1[folder][2]-=mp[folder][file];
            mp1[folder][3]-=mp[folder][file];
            mp[folder][file]=0;  //文件大小置为0
        }
        else if(mpY[t]==1){
            //迭代器找到mp1在某一范围内的,并删除 (因为map是按顺序排放的)
            //对所有先序结点配额值的修改
            auto start1=mp.find(t);
            string s=t;
            s.back()+=1;
            auto end1=mp.find(s);
            mp.erase(start1,end1);   //删除所有的孩子结点

            int pos=t.find_last_of('/');
            string folder=t.substr(0,pos);
            string file=t.substr(pos+1);
            mp1["/"][3]-=mp1[t][3];
            int p=1;  //对所有的父文件配额进行修改
            while((p=t.find('/',p))!=pos&&p!=-1){
                string s=t.substr(0,p);
                mp1[s][3]-=mp1[t][3]; //否则就将其配额值进行增加
                p++;
            }
            auto start=mp1.find(t);  //下面三个只是一种形式上的删除
            auto end=mp1.find(s);
            mp1.erase(start,end);   //删除中间的元素

            auto start2=mpY.find(t);
            auto end2=mpY.find(s);
            mpY.erase(start2,end2);   //删除中间的元素
        }
        return true;
    };
    auto qua=[&](string t,int i,int j)->bool {
        //先通过mpY判断是否存在这个文件或目录
        //与2、3的下标进行比较,并修改0、1下标即可
        if(mpY[t]!=1||(i!=0&&i<mp1[t][2])||(j!=0&&j<mp1[t][3]))
            return false;
        else{
            mp1[t][0]=i;
            mp1[t][1]=j;
            return true;
        }
    };
    for(int i=0;i<n;i++){
        string s,temp;
        getline(cin,s);
        //最多可以分解为4个子串
        vector<string> v;
        stringstream ss(s);
        //保存当前结点的孩子配额值[0]和后代的配额值[1],已分配的孩子配额值[2],已分配的后代配额值[3]
        while(ss>>temp)
            v.push_back(temp);
        //对第一个参数进行判断
        //带数字或字母都有可能是目录或文件
        switch (v[0][0]) {
            case 'C': cout<<(create(v[1],stoi(v[2]))?'Y':'N')<<endl;break;
            case 'R': cout<<(remove(v[1])?'Y':'N')<<endl;break;
            case 'Q': cout<<(qua(v[1],stoi(v[2]),stoi(v[3]))?'Y':'N')<<endl;break;
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值