http://118.190.20.162/view.page?gpid=T121
代码长度 | 编程语言 | 得分 | 时间使用 | 空间使用 |
---|---|---|---|---|
7.515KB | CPP11 | 100 | 671ms | 16.47MB |
#include
#include
#include
#include
#include
using namespace std;
// #define DEBUG(cmd) cmd;
#define DEBUG(cmd) ;
template <typename T>
void print(const vector<T>& v) {
for (const auto& e : v) {
cout << e << " ";
}
cout << endl;
}
namespace path {
void split(vector<string>& result, const string& filepath) {
assert(result.size() == 0);
for (int i = 1, j; i < filepath.size(); i = j + 1) {
for (j = i; j < filepath.size() && filepath[j] != '/'; j++);
result.push_back(filepath.substr(i, j - i));
}
}
void dirname(vector<string>& result, const vector<string>& filepath) {
assert(result.size() == 0);
result.insert(result.begin(), filepath.begin(), filepath.end() - 1);
}
void basename(string& result, const vector<string>& filepath) {
assert(result.size() == 0);
result = filepath.back();
}
}
class Directory {
map<string, Directory*> _directories;
map<string, int> _files;
unsigned long long _directSize = 0, _size = 0, _ld = 0, _lr = 0;
friend void _tree(Directory* root, const string& dirname, const unsigned long long indent);
public:
bool hasSubDirectory(const string& name) const {
return _directories.count(name) > 0;
}
bool hasFile(const string& name) const {
return _files.count(name) > 0;
}
bool hasDirectFreeSpace(const unsigned long long size) const {
return _ld == 0 || _directSize + size <= _ld;
}
bool hasFreeSpace(const unsigned long long size) const {
return _lr == 0 || _size + size <= _lr;
}
Directory* getSubDirectory(const string& name) {
return _directories.at(name);
}
unsigned long long getSize(void) const {
return _size;
}
unsigned long long getFileSize(const string& name) const {
return _files.at(name);
}
Directory* createSubDirectory(const string& name) {
_directories[name] = new Directory();
return _directories[name];
}
void createFile(const string& name, const unsigned long long size) {
if (hasFile(name)) {
_directSize -= _files[name];
}
_files[name] = size;
_directSize += size;
}
void allocate(const unsigned long long size) {
_size += size;
}
void free(const unsigned long long size) {
_size -= size;
}
void unlinkFile(const string& name) {
_directSize -= _files[name];
_files.erase(name);
}
void unlinkDir(const string& name) {
delete _directories[name];
_directories.erase(name);
}
bool quota(const unsigned long long ld, const unsigned long long lr) {
if (0 < ld && ld < _directSize) {
return false;
}
if (0 < lr && lr < _size) {
return false;
}
_ld = ld;
_lr = lr;
return true;
}
};
void _tree(Directory* root, const string& dirname, const unsigned long long indent) {
cout << string(indent, ' ') << dirname << "(directSize=" << root->_directSize << ", size=" << root->_size << ", ld=" << root->_ld << ", lr=" << root->_lr << ")" << endl;
for (const auto& file : root->_files) {
cout << string(indent + 2, ' ') << file.first << "(size=" << file.second << ")" << endl;
}
for (const auto& directory : root->_directories) {
_tree(directory.second, directory.first, indent + 2);
}
}
class FileSystem {
Directory _root;
Directory* _getDirectory(const vector<string>& dirnameParts) {
Directory* dir = &_root;
for (const string& dirnamePart : dirnameParts) {
if (!dir->hasSubDirectory(dirnamePart)) {
return nullptr;
}
dir = dir->getSubDirectory(dirnamePart);
}
return dir;
}
void _allocate(const vector<string>& dirnameParts, const unsigned long long size) {
Directory* dir = &_root;
dir->allocate(size);
for (const string& dirnamePart : dirnameParts) {
dir = dir->getSubDirectory(dirnamePart);
dir->allocate(size);
}
}
void _free(const vector<string>& dirnameParts, const unsigned long long size) {
Directory* dir = &_root;
dir->free(size);
for (const string& dirnamePart : dirnameParts) {
dir = dir->getSubDirectory(dirnamePart);
dir->free(size);
}
}
bool _checkFreeSpace(const vector<string>& dirnameParts, const unsigned long long size) {
Directory* dir = &_root;
if (!dir->hasFreeSpace(size)) {
return false;
}
for (const string& dirnamePart : dirnameParts) {
dir = dir->getSubDirectory(dirnamePart);
if (!dir->hasFreeSpace(size)) {
return false;
}
}
return dir->hasDirectFreeSpace(size);
}
Directory* _createDirectories(const vector<string>& dirnameParts, const unsigned long long size) {
Directory* dir = &_root;
if (!dir->hasFreeSpace(size)) {
return nullptr;
}
int i;
for (i = 0; dir->hasSubDirectory(dirnameParts[i]); i++) {
dir = dir->getSubDirectory(dirnameParts[i]);
if (!dir->hasFreeSpace(size)) {
return nullptr;
}
}
if (dir->hasFile(dirnameParts[i])) {
return nullptr;
}
for (; i < dirnameParts.size(); i++) {
dir = dir->createSubDirectory(dirnameParts[i]);
}
return dir;
}
public:
bool create(const vector<string>& filepath, unsigned long long size) {
DEBUG(cout << "create" << endl << "filepath: "; print(filepath); cout << "size: " << size << endl;)
vector<string> dirnameParts;
path::dirname(dirnameParts, filepath);
string basename("");
path::basename(basename, filepath);
Directory* dir = _getDirectory(dirnameParts);
if (dir == nullptr) {
dir = _createDirectories(dirnameParts, size);
if (dir == nullptr) {
return false;
}
_allocate(dirnameParts, size);
} else if (dir->hasFile(basename)) {
unsigned long long oldSize = dir->getFileSize(basename);
if (size > oldSize) {
if (!_checkFreeSpace(dirnameParts, size - oldSize)) {
return false;
}
_allocate(dirnameParts, size - oldSize);
} else {
_free(dirnameParts, oldSize - size);
}
} else if (dir->hasSubDirectory(basename)) {
return false;
} else {
if (!_checkFreeSpace(dirnameParts, size)) {
return false;
}
_allocate(dirnameParts, size);
}
dir->createFile(basename, size);
return true;
}
bool remove(const vector<string>& filepath) {
DEBUG(cout << "remove" << endl << "filepath: "; print(filepath);)
vector<string> dirnameParts;
path::dirname(dirnameParts, filepath);
string basename("");
path::basename(basename, filepath);
Directory* dir = _getDirectory(dirnameParts);
if (dir != nullptr) {
if (dir->hasFile(basename)) {
unsigned long long size = dir->getFileSize(basename);
_free(dirnameParts, (unsigned long long) size);
dir->unlinkFile(basename);
} else if (dir->hasSubDirectory(basename)) {
unsigned long long size = dir->getSubDirectory(basename)->getSize();
_free(dirnameParts, size);
dir->unlinkDir(basename);
}
}
return true;
}
bool quota(const vector<string>& filepath, unsigned long long ld, unsigned long long lr) {
DEBUG(cout << "quota" << endl << "filepath: "; print(filepath); cout << "ld: " << ld << ", lr: " << lr << endl;)
Directory* dir = _getDirectory(filepath);
if (dir == nullptr) {
return false;
}
return dir->quota(ld, lr);
}
void tree(void) {
_tree(&_root, "/", 0);
}
};
int main() {
FileSystem fs;
int n;
for (cin >> n; n > 0; n--) {
char op;
string filepath;
unsigned long long size;
unsigned long long ld, lr;
vector<string> filepathParts;
bool result = false;
cin >> op >> filepath;
path::split(filepathParts, filepath);
switch (op) {
case 'C':
cin >> size;
result = fs.create(filepathParts, size);
break;
case 'R':
result = fs.remove(filepathParts);
break;
case 'Q':
cin >> ld >> lr;
result = fs.quota(filepathParts, ld, lr);
break;
default:
break;
}
DEBUG(cout << "FileSystem:" << endl; fs.tree();)
cout << (result ? 'Y' : 'N') << endl;
}
return 0;
}