csp20-12-3带配额的文件系统-70分无语版

这道模拟题我做了两个半小时,最开始只有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;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值