#include<iostream>
#include<map>
#include<vector>
#include<regex>
#define max 2e+18
using namespace std;
typedef long long ll;
enum retype{
notexist,isfile,iscata
};//next函数的返回枚举,分别表示文件不存在,文件为普通文件,文件为目录文件
typedef struct files{
int type;//文件类型,0目录文件,1普通文件
string name;
ll ld=0,lr=0,sd=0,sr=0;
map<string,struct files>child;// key值string为文件夹下子文件名
}file;
ll lrmin;//路径中lr产生的最小限额
file root;//根目录
file *nowcata;//指向当前正在被操作的文件夹
vector<file* > cv;//记录路径用以回溯
void init(){//每次操作时的初始化函数
lrmin=max;
nowcata=&root;
cv.clear();
}
bool setL(ll nld,ll nlr){//尝试对当前文件夹设置新的ld和lr
//cout<<nowcata->sd<<":"<<nowcata->sr<<endl;
if((nld==0||nowcata->sd<=nld)&&(nlr==0||nowcata->sr<=nlr)){
nowcata->ld=nld;
nowcata->lr=nlr;
return true;
}else{
return false;
}
}
bool changeS(ll csd,ll csr){//尝试修改当前文件的sd和sr
if((nowcata->ld==0||nowcata->ld>=nowcata->sd+csd)&&(nowcata->lr==0||nowcata->lr>=nowcata->sr+csr)){
nowcata->sd+=csd;
nowcata->sr+=csr;
//cout<<nowcata->name<<":\tsd:"<<nowcata->sd<<"\tsr:"<<nowcata->sr<<endl;
return true;
}else{
cout<<"flase"<<endl;
return false;
}
}
retype next(string s){//尝试进入名为s的子文件夹
if(nowcata->child.find(s)==nowcata->child.end()){
return notexist;
}else{
if(nowcata->child[s].type==1){
return isfile;
}else{
cv.push_back(nowcata);
nowcata=&nowcata->child[s];
if(nowcata->lr!=0&&nowcata->lr-nowcata->sr<lrmin){
lrmin=nowcata->lr-nowcata->sr;//更新lrmin
}
return iscata;
}
}
}
bool back(){//尝试回到上一级文件夹
if(cv.empty()){
return false;
}else{
auto it=cv.end();
it--;
nowcata=*it;
cv.pop_back();
return true;
}
}
bool delect(string s){//尝试删除当前文件夹下名为s的文件,并修改所有上级文件夹的sr和sd;
retype re;
ll fs;
re=next(s);
if(re==notexist){
return false;
}else if(re==isfile){
fs=nowcata->child[s].sr;
nowcata->child.erase(s);
nowcata->sd-=fs;
nowcata->sr-=fs;
while(back()){
changeS(0,-fs);
}
return true;
}else{
back();
fs=nowcata->child[s].sr;
nowcata->child.erase(s);
nowcata->sr-=fs;
while(back()){
changeS(0,-fs);
}
return true;
}
}
bool CC(string s){//创建一个新的子文件夹
file node;
node.name=s;
node.type=0;
nowcata->child.insert(make_pair(s,node));
return true;
}
bool CF(string s,ll fs){//尝试在当前文件夹创建一个新的文件,或修改已存在的文件,最后修改所有上级文件夹的sr和sd;
retype re;
re=next(s);
ll xfs;
file node;
node.name=s;
node.sd=fs;
node.sr=fs;
node.type=1;
if(re==iscata){
return false;
}else if(re==isfile){
xfs=fs-nowcata->child[s].sr;
}else{
xfs=fs;
}
if(xfs>lrmin||(nowcata->ld!=0&&nowcata->sd+xfs>nowcata->ld)){
return false;
}
nowcata->child.insert(make_pair(s,node));
nowcata->child[s].sr=fs;
nowcata->child[s].sd=fs;
changeS(xfs,xfs);
while(back()){
changeS(0,xfs);
}
return true;
}
vector<string> s2v(string s){//将路径以“/”分割为string向量返回;
vector<string> re;
string ds="root";
ds.append(s);
regex reg("/");
sregex_token_iterator pos(ds.cbegin(),ds.cend(),reg,-1);
sregex_token_iterator end;
for(;pos!=end;pos++){
//cout<<pos->str()<<endl;
re.push_back(pos->str());
}
return re;
}
bool Copp(string ds){//创建操作
ll fs;
cin>>fs;
init();
vector<string> fp=s2v(ds);
auto it=fp.end();
it--;
string f=*it;
fp.pop_back();
retype re;
for(it=fp.begin();it!=fp.end();it++){
re=next(*it);
if(re==isfile){
return false;
}else if(re==notexist){
break;
}else{
continue;
}
}
for(;it!=fp.end();it++){
if(fs<=lrmin){
CC(*it);
next(*it);
}else{
return false;
}
}
return CF(f,fs);
}
bool Ropp(string s){//删除操作
vector<string> fp=s2v(s);
init();
auto it=fp.end();
it--;
string f=*it;
fp.pop_back();
retype re;
for(it=fp.begin();it!=fp.end();it++){
re=next(*it);
if(re==iscata){
continue;
}else{
return true;
}
}
delect(f);
return true;
}
bool Qopp(string s){//修改配额操作
ll nld,nlr;
cin>>nld>>nlr;
init();
vector<string> fp=s2v(s);
auto it=fp.end();
retype re;
for(it=fp.begin();it!=fp.end();it++){
re=next(*it);
if(re==iscata){
continue;
}else{
return false;
}
}
return setL(nld,nlr);
}
int main(){
int n;
string t,ds;
file node;
node.name="root";
node.type=0;
root.child.insert(make_pair("root",node));
cin>>n;
for(int i=0;i<n;i++){
cin>>t>>ds;//只读取操作符和路径
if(t=="C"){
if(Copp(ds)){
cout<<"Y"<<endl;
}else{
cout<<"N"<<endl;
}
}else if(t=="R"){
Ropp(ds);
cout<<"Y"<<endl;
}else{
if(Qopp(ds)){
cout<<"Y"<<endl;
}else{
cout<<"N"<<endl;
}
}
}
return 0;
}
好好写过注释了,这题的问题不是在于难不难,而是代码要写的足够干净。一个小技巧是,创建文件时,我并没有回溯检查是否满足配额限制,而是在dfs的过程中记录当前lr-sr的最小值为lrmin,只要创建文件所增加的容量小于lrmin,即可创建成功。