大模拟,没涉及什么算法主要是数据结构的设计、细节的考虑,挺锻炼的,记录一下,代码加了注释。
#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;
}