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;
}