题目
题目大意
本题主要给出了对于目录操作的一些过程,并按要求做出输出。主要过程包含在题目中,需要认真读题理解。
解题思路
本题是一道非常复杂的模拟问题,所以在做题时一定要首先细致读题。本题我通过借鉴学长课上所讲解的方法,按照学长思路来完成。本题首先要构造出管理目录与管理命令的结构体,在此基础上使思路更加清晰,便于解题。本题要注意的几个地方是树的构建以及命令更新的操作,树的构造可以根据相关的思路和代码来完成,所以主要还是对于命令的操作比较复杂。tree命令主要是输出结构,ls命令也是输出目录,这些按照题目要求不难实现;sz用于输出size,这在每个结构体中都有记录;mkdir的作用其实就是在树中建立新的边,注意其中的建立关系;cd和rm用于移动和删除目录,这里操作相对复杂,但只要细致思考,还是可以得到解决方法的。
本题在对照学长的情况下做出,总的来说还是需要提升这方面的能力,这样才能应对之后更复杂的模拟类问题。
具体代码
#include <bits/stdc++.h>
#define ll long long
#define MAXN 100005
#define inf 1e9
using namespace std;
string tmps;
struct Directory{
string name;
map<string, Directory*> children;
Directory* parent;
int subtreeSize;
bool updated;
vector<string>* tenDescendants = new vector<string>;
Directory(string name, Directory* parent){
this->name = name;
this->parent = parent;
this->subtreeSize = 1;
}
public:
Directory* getChild(string name)
{
if(children.find(name) == children.end())
{
return NULL;
}
return children.find(name)->second;
}
Directory* mkdir(string name)
{
if(children.find(name) != children.end())
{
return NULL;
}
Directory* ch = new Directory(name, this);
children[name] = ch;
maintain(+1);
return ch;
}
Directory* rm(string name)
{
map<string,Directory*>::iterator it = children.find(name);
if(it == children.end())
{
return NULL;
}
maintain(-1 * it->second->subtreeSize);
children.erase(it);
return it->second;
}
Directory* cd(string name)
{
if(".." == name)
{
return this->parent;
}
return getChild(name);
}
bool addChild(Directory* ch)
{
if(children.find(ch->name) != children.end())
{
return false;
}
children[ch->name] = ch;
maintain(+ch->subtreeSize);
return true;
}
void maintain(int delta)
{
updated = true;
subtreeSize += delta;
if(parent != NULL)
{
parent->maintain(delta);
}
}
void sz()
{
printf("%d\n",this->subtreeSize);
}
void ls()
{
int sz = children.size();
if(sz == 0)
{
printf("EMPTY\n");
}
else if(sz <= 10)
{
map<string,Directory*>::iterator it;
for(it = children.begin(); it != children.end(); it++)
{
printf("%s\n",it->first.c_str());
}
}
else
{
map<string,Directory*>::iterator it = children.begin();
for(int i = 0; i < 5; i++, it++)
{
printf("%s\n",it->first.c_str());
}
printf("...\n");
it = children.end();
for(int i = 0; i < 5; i++)
{
it--;
}
for(int i = 0; i < 5; i++, it++)
{
printf("%s\n",it->first.c_str());
}
}
}
void tree()
{
if(subtreeSize == 1)
{
printf("EMPTY\n");
}
else if(subtreeSize <= 10)
{
if(this->updated)
{
tenDescendants->clear();
treeAll(tenDescendants);
this->updated = false;
}
for(int i = 0; i < subtreeSize; i++)
{
printf("%s\n",tenDescendants->at(i).c_str());
}
}
else
{
if(this->updated)
{
tenDescendants->clear();
treeFirstSome(5,tenDescendants);
treeLastSome(5,tenDescendants);
this->updated = false;
}
for(int i = 0; i < 5; i++)
{
printf("%s\n",tenDescendants->at(i).c_str());
}
printf("...\n");
for(int i = 9; i >= 5; i--)
{
printf("%s\n",tenDescendants->at(i).c_str());
}
}
}
private:
void treeAll(vector<string>* bar)
{
bar->push_back(name);
map<string,Directory*>::iterator it;
for(it = children.begin(); it != children.end(); it++)
{
it->second->treeAll(bar);
}
}
void treeFirstSome(int num, vector<string>* bar)
{
bar->push_back(name);
if(--num == 0)
{
return;
}
int n = children.size();
map<string,Directory*>::iterator it = children.begin();
while(n--)
{
int sts = it->second->subtreeSize;
if(sts >= num)
{
it->second->treeFirstSome(num,bar);
return;
}
else
{
it->second->treeFirstSome(sts,bar);
num-= sts;
}
it++;
}
}
void treeLastSome(int num, vector<string>* bar)
{
int n = children.size();
map<string,Directory*>::iterator it = children.end();
while(n--)
{
it--;
int sts = it->second->subtreeSize;
if(sts >= num)
{
it->second->treeLastSome(num,bar);
return;
}
else
{
it->second->treeLastSome(sts,bar);
num -= sts;
}
}
bar->push_back(name);
}
};
struct Command{
Directory* tmpDir;
const string CMDNAMES[7] = {"MKDIR","RM","CD","SZ","LS","TREE","UNDO"};
int type;
string arg;
Command(string s){
for(int i = 0; i < 7; i++)
{
if(CMDNAMES[i] == s)
{
type = i;
if(i < 3)
{
cin >> tmps;
arg = tmps;
}
break;
}
}
}
};
void solve()
{
int n;
scanf("%d",&n);
Directory* now = new Directory("root", NULL);
vector<Command*> cmdList;
while(n--)
{
cin >> tmps;
Command* cmd = new Command(tmps);
switch(cmd->type)
{
case 0:case 1:
{
cmd->tmpDir = cmd->type == 0 ? now->mkdir(cmd->arg) : now->rm(cmd->arg);
if(cmd->tmpDir == NULL)
{
printf("ERR\n");
}
else
{
printf("OK\n");
cmdList.push_back(cmd);
}
break;
}
case 2:
{
Directory* ch = now->cd(cmd->arg);
if(ch == NULL)
{
printf("ERR\n");
}
else
{
printf("OK\n");
cmd->tmpDir = now;
now = ch;
cmdList.push_back(cmd);
}
break;
}
case 3: now->sz(); break;
case 4: now->ls(); break;
case 5: now->tree(); break;
case 6:
{
bool success = false;
while(!success && !cmdList.empty())
{
cmd = cmdList.back();
cmdList.pop_back();
switch(cmd->type)
{
case 0: success = now->rm(cmd->tmpDir->name) != NULL; break;
case 1: success = now->addChild(cmd->tmpDir); break;
case 2: now = cmd->tmpDir; success=true; break;
}
}
printf(success ? "OK\n" : "ERR\n");
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}