CCF 带配额的文件系统 100分
#include <cstdio>
#include <map>
#include <vector>
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cassert>
using namespace std;
typedef long long ll;
struct Node {
string name;
map<string, Node*> child;
Node* father;
bool dir;
ll Q1, Q2;
ll size1, size2;
ll filesize;
Node(bool _dir) {
father=NULL;
dir=_dir;
Q1=Q2=0;
size1=size2=0;
filesize=0;
}
};
Node* root;
vector<string> Path;
void Init() {
root=new Node(true);
}
#define MAXP 1024
void Parse(string& str) {
Path.clear();
int i=0;
int len=str.size();
while (i<len) {
while (i<len && str[i]=='/') {
++i;
}
if (i>=len) break;
string p;
while (i<len && str[i] != '/') {
p.push_back(str[i]);
++i;
}
Path.push_back(p);
}
}
bool Create(string& str, ll size) {
Parse(str);
assert(Path.size());
Node* p=root;
int i=0;
while (i<Path.size()) {
string& n=Path[i];
if (!p->dir) {
return false;
}
if (!p->child.count(n)) {
break;
}
p=p->child[n];
++i;
}
assert(p);
if (i == Path.size()) {
if (p->dir) {
return false;
}
ll diff=size-p->filesize;
Node* fa=p->father;
assert(fa->dir);
if (fa && fa->Q1 && fa->size1+diff > fa->Q1) {
return false;
}
while (fa) {
if (fa->Q2 && fa->size2+diff > fa->Q2) {
return false;
}
fa=fa->father;
}
string& name=Path.back();
assert(p->name == name);
fa=p->father;
p->filesize=size;
fa->size1 += diff;
while (fa) {
fa->size2 += diff;
fa=fa->father;
}
return true;
}
if (i == Path.size()-1) {
assert(p->dir);
if (p->Q1 && p->size1 + size > p->Q1) {
return false;
}
}
Node* fa=p;
while (fa) {
if (fa->Q2 && fa->size2 + size > fa->Q2) {
return false;
}
fa=fa->father;
}
while (i!=Path.size()-1) {
Node* dir=new Node(true);
dir->name=Path[i];
assert(!p->child.count(dir->name));
p->child[dir->name]=dir;
dir->father=p;
p=dir;
++i;
}
Node* file=new Node(false);
assert(i==Path.size()-1);
file->name=Path[i];
file->filesize=size;
file->father=p;
p->child[file->name]=file;
fa=file->father;
assert(fa);
fa->size1 += size;
while (fa) {
fa->size2 += size;
fa=fa->father;
}
return true;
}
void Print(Node* p) {
if (!p->dir) {
printf("%s %lld\n", p->name.c_str(), p->filesize);
} else {
printf("/%s size1 %lld size2 %lld Q1 %lld Q2 %lld\n",
p->name.c_str(), p->size1, p->size2, p->Q1, p->Q2);
for (map<string,Node*>::iterator it=p->child.begin();it != p->child.end();++it) {
Print(it->second);
}
}
}
bool Check(Node* p) {
if (!p->dir) return true;
assert(p->size1 >= 0);
assert(p->size2 >= 0);
assert(p->size1 <= p->size2);
if (p->Q1 && p->size1 > p->Q1) return false;
if (p->Q2 && p->size2 > p->Q2) return false;
for (map<string,Node*>::iterator it=p->child.begin();it!=p->child.end();++it) {
if (!Check(it->second)) return false;
}
return true;
}
void Delete(Node* p) {
if (p) {
for (map<string,Node*>::iterator it=p->child.begin();it!=p->child.end();++it) {
Delete(it->second);
}
delete p;
}
}
bool Remove(string& str) {
Parse(str);
assert(Path.size());
Node* p=root;
int i=0;
while (i<Path.size()) {
string& n=Path[i];
if (!p->dir) {
return true;
}
if (!p->child.count(n)) {
return true;
}
p=p->child[n];
assert(p);
++i;
}
assert(p);
if (p->dir) {
ll size2=p->size2;
Node* fa=p->father;
while (fa) {
fa->size2 -= size2;
assert(fa->size2 >= 0);
fa=fa->father;
}
} else {
ll size=p->filesize;
Node* fa=p->father;
assert(fa);
fa->size1 -= size;
assert(fa->size1>=0);
while (fa) {
fa->size2 -= size;
assert(fa->size2>=0);
fa=fa->father;
}
}
assert(p->father);
assert(p->father->child.count(p->name));
p->father->child.erase(p->name);
Delete(p);
return true;
}
bool Quota(string& str, ll Q1, ll Q2) {
Parse(str);
int i=0;
Node* p=root;
while (i<Path.size()) {
string& n=Path[i];
if (!p->dir) {
return false;
}
if (!p->child.count(n)) {
return false;
}
p=p->child[n];
++i;
}
if (!p->dir) {
return false;
}
if ((Q1 && p->size1 > Q1) || (Q2 && p->size2 > Q2)) {
return false;
}
p->Q1=Q1;
p->Q2=Q2;
return true;
}
int main(int argc, char** argv) {
string str;
Init();
int N;
scanf("%d", &N);
while (N--) {
char op;
cin >> op;
ll size;
ll Q1, Q2;
bool ans=false;
switch (op) {
case 'C':
cin >> str >> size;
ans=Create(str, size);
break;
case 'R':
cin >> str;
ans=Remove(str);
break;
case 'Q':
cin >> str >> Q1 >> Q2;
ans=Quota(str, Q1, Q2);
break;
default:
assert(false);
}
puts(ans?"Y":"N");
}
return 0;
}