week9 作业A 咕咕东的目录管理器

咕咕东的目录管理器

咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 —— 这工程量太大了,所以他定了一个小目标,从实现一个目录管理器开始。前些日子,东东的电脑终于因为过度收到宇宙射线的影响而宕机,无法写代码。他的好友TT正忙着在B站看猫片,另一位好友瑞神正忙着打守望先锋。现在只有你能帮助东东!
初始时,咕咕东的硬盘是空的,命令行的当前目录为根目录 root。
目录管理器可以理解为要维护一棵有根树结构,每个目录的儿子必须保持字典序。
在这里插入图片描述现在咕咕东可以在命令行下执行以下表格中描述的命令:
在这里插入图片描述

Input

输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);
每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);
每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。

Output

每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。

Limit

Time limit 6000 ms
Memory limit 1048576 kB

Sample Input

1
22
MKDIR dira
CD dirb
CD dira
MKDIR a
MKDIR b
MKDIR c
CD …
MKDIR dirb
CD dirb
MKDIR x
CD …
MKDIR dirc
CD dirc
MKDIR y
CD …
SZ
LS
TREE
RM dira
TREE
UNDO
TREE

Sample Output

OK
ERR
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
9
dira
dirb
dirc
root
dira
a
b
c
dirb
x
dirc
y
OK
root
dirb
x
dirc
y
OK
root
dira
a
b
c
dirb
x
dirc
y

我的思路:
这道题是一道较为复杂的模拟题,要求我们实现一个目录管理器的功能。如果只是暴力的话,时间复杂度会过大,所以在TREE和SZ上,要做一定的优化。需要在每一个节点里设置一个sz,用于统计以当前节点为根节点的树的节点个数(包括当前节点,所以每个节点的初始sz值为1)。TREE则需要为每个节点设置一个标签,判断是否已经访问过了,这样也会节省一些时间。还有要注意的是,RM只是删除边而不删除节点,因为UNDO操作的存在,保留节点后,RM的UNDO是直接连上边就可以了。(注意需要记录MKDIRs、RMs和CDs的操作,为UNDO做准备)。

我的总结:
对于一道模拟题,不要直接按照最开始的想法直接coding,而是要观察一下时间和空间限制,然后对于数据结构和算法做一下调整,符合题目的限制要求是最重要的。

我的代码:

#include <iostream>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int T,Q;

struct comm{
	string nam,lan;
	int typ;
	void init(string st){
		nam=st;
	}
}cmd;
struct Dic{
	string nam;
	int fa,sz;
	vector<string > pre,bck;
	bool tag;
	map<string,int > mm;
	void init(string st,int f)
	{
		tag=false;
		fa=f;
		sz=1;
		nam=st;
		pre.clear();
		bck.clear();
		mm.clear();
	}
}node[200000];

int ind,now;
vector<pair<string, pair<int, int> > > coms;

void update(int id,int numm)
{
	while(id!=-1){
		node[id].tag=false;
		node[id].sz+=numm;
		id=node[id].fa;
	}
}

void make_node(string s,int p) {
	node[++ind].init(s,p);
	node[p].mm[s]=ind;
}

void mkdir(){
	if(!node[now].mm.count(cmd.lan))
	{
 		make_node(cmd.lan,now);
		update(now,1);
		cout<<"OK"<<endl;
		coms.push_back(make_pair(cmd.nam,make_pair(now,ind)));
	}
	else
		cout<<"ERR"<<endl;
}

void rm(){
	if(node[now].mm.count(cmd.lan)) 
	{
		int ind1=node[now].mm[cmd.lan];
		update(now,-node[ind1].sz);
		node[now].mm.erase(node[ind1].nam);
		cout<<"OK"<<endl;
		coms.push_back(make_pair(cmd.nam,make_pair(now,ind1)));
	}
	else cout<<"ERR"<<endl;
}

void cd(){
	
	if(cmd.lan=="..")
	{
		if(node[now].fa!=-1)
		{
			coms.push_back(make_pair(cmd.nam,make_pair(now,node[now].fa)));
			now=node[now].fa;
			cout<<"OK"<<endl;
		}
		else cout<<"ERR"<<endl;
	}
	else
	{
		if(node[now].mm.count(cmd.lan))
		{
			int ind1=node[now].mm[cmd.lan];
			coms.push_back(make_pair(cmd.nam,make_pair(now,ind1)));
			now=ind1;
			cout<<"OK"<<endl;
			
		}
		else cout<<"ERR"<<endl;
	}
}

void sz() 
{
	cout << node[now].sz << endl;
}
void undo(){
	if(coms.size()==0) {cout<<"ERR"<<endl;return;}
	auto st=coms[coms.size()-1];
	coms.pop_back();
	int temp=now;
	if(st.first=="MKDIR"){
		cmd.nam="RM";
		now=st.second.first;
		cmd.lan=node[st.second.second].nam;
		int ind1=node[now].mm[cmd.lan];
		update(now,-node[ind1].sz);
		node[now].mm.erase(node[ind1].nam);
		now=temp;
	}
	else if(st.first=="RM"){
		now=st.second.first;
		int ind1=st.second.second;
		update(now,node[ind1].sz);
		node[now].mm[node[ind1].nam] = ind1;
		now = temp;
	}
	else{
		now = st.second.first;
	}
	cout<<"OK"<<endl;
}

void ls(){
	int tt=node[now].mm.size();
	if(tt==0){
		cout<<"EMPTY"<<endl;
		return;
	}
	auto pos = node[now].mm.begin();
	if(tt>=1&&tt<=10){
		while(pos!=node[now].mm.end())
		{
			cout<<pos->first<<endl;
			pos++;
		}
		return;
	}
	for(int i=0;i<5;i++)
	{
		cout<<pos->first<<endl;
		pos++;
	}
	cout<<"..."<<endl;
	pos = node[now].mm.end();
	for(int i=0;i<5;i++) pos--;
	for(int i=0;i<5;i++)
	{
		cout<<pos->first<<endl;
		pos++;
	}
}

void pushdown(int x);

void pretrack(int x) {
	node[x].pre.push_back(node[x].nam);
	if (node[x].sz==1)return;
	if (node[x].sz<=10) 
	{
		for (auto i:node[x].mm) 
		{
			if (!node[i.second].tag) pushdown(i.second);
			node[x].pre.insert(node[x].pre.end(),node[i.second].pre.begin(), node[i.second].pre.end());
		}
		return;
	}
	int pos = 1;
	for (auto i : node[x].mm) {
		if (!node[i.second].tag)pushdown(i.second);
		for (auto ii : node[i.second].pre) 
		{
			node[x].pre.push_back(ii);
			pos++;
			if (pos >= 5)break;
		}
		if (pos >= 5)break;
	}
}

void bcktrack(int x) {
	auto pos = node[x].mm.end();
	pos--;
	int pos1=0;
	for (;;pos--) 
	{
		int ind1=pos->second;
		if (!node[ind1].tag) pushdown(ind1);
		for (int i=node[ind1].bck.size()-1; i >= 0; i--) {
			node[x].bck.push_back(node[ind1].bck[i]);
			pos1++;
			if(pos1>=5) 
			{
				reverse(node[x].bck.begin(), node[x].bck.end());
				break;
			}
		}
		if(pos1>=5)break;
		if(pos==node[x].mm.begin())break;
	}
}

void pushdown(int id){
	node[id].pre.clear();
	node[id].bck.clear();
	pretrack(id);
	if(node[id].sz > 10) bcktrack(id);
	else node[id].bck = node[id].pre;
	node[id].tag=true;
}

void tree(){
	if(!node[now].tag) pushdown(now);
	if(node[now].sz==1) cout<<"EMPTY"<<endl;
	else if(node[now].sz>1&&node[now].sz<=10){
		for(int i=0;i<node[now].pre.size();i++) cout<<node[now].pre[i]<<endl;		 
	}
	else{
		for(int i=0;i<5;i++) cout<<node[now].pre[i]<<endl;
		cout<<"..."<<endl;
		for(int i=5;i>=1;i--) cout<<node[now].bck[node[now].bck.size()-i]<<endl;
	}
}

void init() {
	ind = now = 0;
	coms.clear();
	node[0].init("root", -1);
}


int main()
{
	cin.sync_with_stdio(false);
	cin>>T;
	while (T--) {
		cin>>Q;
		init();
		while(Q--)
		{
			string s;
			cin>>s;
			cmd.init(s);
			if(cmd.nam=="MKDIR") cin>>cmd.lan,mkdir();
			else if(cmd.nam=="RM") cin>>cmd.lan,rm();
			else if(cmd.nam=="CD") cin>>cmd.lan,cd();
			else if(cmd.nam=="SZ") sz();
			else if(cmd.nam=="LS") ls();
			else if(cmd.nam=="TREE") tree();
			else undo();
		}
	}


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值