这道模拟题我做了两个半小时,最开始只有50分,很崩溃。后面才发现没有关注文件大小,不该定义为int,应该为long long。改掉类型之后,跑出来有70分。改了很久没有发现自己错在哪,先记录一下。但是做这道题发现自己模拟题的速度太慢了,希望后面几天能够提高一下速度。
我模拟题都写得很繁琐,感觉自己逻辑有点混乱,反正很不简洁,大家不要太参考了。希望后面做模拟题能够思路清晰,代码简洁一点。
//2012-3带配额的文件系统
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int idx=1;
struct Node {
int id; // 编号
string name; // 文件名
int type; // 0--目录 1--普通文件
ll ld, lr; // 配额
set<Node> sun; // 孩子
ll sun_size; // 孩子占比
ll suns_size; // 后代占比
ll size;
int far; // 双亲的编号(逆向指)
bool operator< (const Node b) const {
return name < b.name; // 字典序
}
Node(){}
Node(int ii, string n, int t, int d, int r, int s, int ss):id(ii), name(n), type(t), ld(d), lr(r), sun_size(s), suns_size(ss){}
Node(string n):name(n){}
}node[300005];
vector<string> lo;
void chuli(string path) {
lo.clear();
string str = path.substr(1); // 除去首部的/
int pos = str.find('/');
while(pos!=string::npos) {
lo.push_back(str.substr(0, pos));
str = str.substr(pos+1);
pos = str.find('/');
}
if(str.length()!=0) lo.push_back(str);
}
// 添加普通文件
void fun1(int size) { // 添加普通文件--目录没有就创建
int index = 0; // 根目录开始查询
for(auto it=lo.begin(); it!=lo.end(); it++) {
auto tt = node[index].sun.find(Node(*it));
// cout << "查看查找的tt:" <<tt->name << " " << tt->type << " " << tt->lr << " " << tt->ld << endl;
if(tt==node[index].sun.end()){ //没有找到---创建---如果为创建的话之后会一直创建,不会出现执行失败的情况
// 查看是否能创建新元素----是否满足配额
if(it==lo.end()-1) {
if((node[index].ld<node[index].sun_size+size&&node[index].ld!=0) || (node[index].lr<node[index].suns_size+size&&node[index].lr!=0)) { // 不成功
cout << "N" << endl; return;
}
}
else if(node[index].lr<node[index].suns_size+size && node[index].lr!=0) { // 不成功
cout << "N" << endl; return;
}
// 创建新元素
node[idx] = Node(idx, *it, 0, 0, 0, 0, 0);
node[idx].id = idx;
node[idx].far = index;
// 对父元素进行信息更新
// cout << "创建新元素" << node[idx].name << " " << node[idx].type << endl;
// cout << "对父元素更新" << node[index].name << " " << node[index].type << endl;
node[index].sun.insert(node[idx]);
// 更新查询信息
index = idx;
idx++;
}
else { // 找到了,则更新新的index,便于下层寻找
// 未达到最后一个文件名
// cout << "添加--查看查找的tt:" <<tt->name << " " << tt->type << " " << tt->lr << " " << tt->ld <<" " << tt->suns_size<< endl;
if(it!=lo.end()-1) {
// 普通文件-执行失败
if(node[tt->id].type==1) {
cout << "N" << endl; return;
}
// 目录文件--判断能否满足配额
if(node[index].lr<node[index].suns_size+size && node[index].lr!=0) { // 不成功
cout << "N" << endl; return;
}
// 更新
index = tt->id;
}
else { // 最后一个文件名---必须为普通文件才能成功
if(node[tt->id].type==1) {
// 普通文件-判断是否满足配额
if((node[index].ld<node[index].sun_size+size&&node[index].ld!=0) || (node[index].lr<node[index].suns_size+size&&node[index].lr!=0)) { // 不成功
cout << "N" << endl; return;
}
// 满足则更新
index = tt->id;
int temp = node[index].size;
// 此时需要将该普通文件涉及的父节点size删除
int tind = node[index].far;
node[tind].sun_size -= temp;
node[tind].suns_size -= temp;
tind = node[tind].far;
while(tind!=-1){
node[tind].suns_size -= temp;
tind = node[tind].far;
}
}
else { // 目录文件--执行失败
cout << "N" << endl; return;
}
}
}
}
// 此时已经到达最终节点 index等于添加的普通文件
node[index].type = 1; // 普通文件
node[index].size = size;
node[index].sun_size = 0;
node[index].suns_size = 0;
index = node[index].far;
node[index].sun_size += size; // 孩子配额
node[index].suns_size += size; // 后代配额
index = node[index].far;
while(index!=-1) {
node[index].suns_size += size;
index = node[index].far;
}
cout << "Y" << endl;
return;
}
// 删除文件
void fun2() {
int index = 0; // 根目录开始查询
bool flag = true;
for(auto it:lo) {
auto tt = node[index].sun.find(Node(it));
if(tt==node[index].sun.end()) {
// 没有找到--不进行任何操作
flag = false;
break;
}
else { // 找到了
index = tt->id; // 到下一个目录去
}
}
if(flag) { // 查找成功--删除文件 ---断开与父节点的联系即可
string nn = node[index].name;
// 判断该文件为目录文件还是普通文件
int ss;
if(node[index].type==1) {
ss = node[index].size;
}
else {
ss = node[index].suns_size;
}
index = node[index].far;
// 在父节点删除该目录文件相关信息
node[index].sun.erase(nn);
node[index].suns_size -= ss;
// 循环删除大小
index = node[index].far;
while(index!=-1) {
node[index].suns_size -= ss;
index = node[index].far;
}
}
cout << "Y" << endl;
return;
}
// 设置配额
void fun3(ll dd, ll rr) {
int index = 0; // 根目录开始查询
bool flag = true;
for(auto it:lo) {
auto tt = node[index].sun.find(Node(it));
if(tt==node[index].sun.end()) {
// 没有找到--不进行任何操作
flag = false;
break;
}
else { // 找到了
index = tt->id; // 到下一个目录去
}
}
if(!flag) { // 路径错误 或 最后为目录文件
cout << "N" << endl; return;
}
if(node[index].type==1) {
cout << "N" << endl; return;
}
// 查找成功---判断配额是否正确
if((node[index].sun_size>dd && dd!=0) || (node[index].suns_size>rr && rr!=0)) { // 不满足
cout << "N" << endl; return;
}
// 配额满足要求,更新新的配额值
node[index].ld = dd;
node[index].lr = rr;
cout << "Y" << endl;
return;
}
int main() {
int n;
cin >> n;
// 初始化根目录
node[0] = Node(0, "", 0, 0, 0, 0, 0);
node[0].far = -1;
string op, path;
ll size, d, r;
for(int i=0; i<n; i++) {
cin >> op >> path;
chuli(path);
if(op=="C") { // 添加普通文件
cin >> size;
fun1(size);
}
else if(op=="R") { // 删除文件
fun2();
}
else if(op=="Q") { // 重新设置配额
cin >> d >> r;
fun3(d, r);
}
}
return 0;
}