A - 咕咕东的目录管理器

2023-05-16

题意:

在这里插入图片描述
在这里插入图片描述
样例输入:

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

样例输出

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

时空限制:
Time limit 6000 ms
Memory limit 1048576 kB


思路:

初见题意,操作非常多。共有7个操作,为了实现这些操作,我们设立一个目录结构体Directory,里面的数据变量有当前目录的名字,他的子目录,由于题目要求子目录必须按照名字的字典序排列,因此我们可以使用map结构,map结构内部实现一棵红黑树保证其有序,并且map提供一对一的hash,这对我们找到目录的某个子目录非常有用,map< string, Directory* >children这样我们便可以通过子目录的名字直接找到对应的子目录,Directory里的数据变量还有他的父节点目录指针,以及他所在的子目录的目录数目,还有一个用来存储最多包含他在内的最多十个目录名字的缓存,以及表示缓存是否更新的bool变量。

我们开始看操作。对于操作我们也需要设立一个结构体来方便管理,共7个操作我们可以设立一个字符数组来帮我们判断是哪个操作,以及为前三个操作设立的一个参数argument,由于我们可能会undo,所以对这个操作的目标目录我们需要设立一个指针指向它,方便撤回操作。

由于操作可能会改变目录里的东西,可能会改变子目录的数目,因此我们设立一个由下往上维护大小的函数void maintain(int del),来帮助我们改变大小。二可能进行的undo操作,则要求我们将类型是前三个的操作用数组记录下来方便我们撤回。

第一个操作“MKDIR s”,是在当前目录下设立一个子目录名为s,我们首先啊判断当前目录有没有一个名为s的目录,若是已有返回NULL用来判断失败,若是没有,则在这个目录的子目录中加入新的目录,即map对象children里加入,并且将这个新的目录返回指针,用来给这个操作对象的目标目录指针赋值,接着将他记录在操作数组里。第二个"RM s"操作则要求我们删除子目录,同样是先判断有没有,有则删除,无则返空,成功的话也要记录下来。第三个"CD s"则操作时进入新的目录中,若是参数时“. .”,则要判断父节点是不是空,若是其他则要判断有没有这个子目录名,成功进入的操作要记录在操作数组里。第四个是"SZ",我们直接输出结构体里表示目录数目的对象即可,第五个是"LS",我们需要分两种情况,若是他直接孩子目录数目在10以内则直接输出,否则遍历前五个和后五个输出。第七个操作是“UNDO”,我们就从之前的指令数组中取出指令,删除了的话则添加,添加了的就删除,进入的就出去。

第六个操作tree操作要非常注意,通过观察题目数据,我们可以看到MKDIR和RM操作非常少,其他的操作很多,这就意味着节点数远远小于tree操作数,可能会有重复操作的情况,因此对于没有改变的情况下,tree的计算过程应该只有一次,因此我们设立了一个最多记录10个目录的数组用作缓存,以及表示更新的bool变量,缓存的更新情况是在MKDIR和RM指令时,而这两个指令会调用maintain函数,所以可以在maintain里设置变量更新为true表示缓存已经更新过,若是缓存没有更新过,那么直接输出,否则则需要重新遍历计算。


总结:

对于这种复杂的模拟题,我们可以先不管细节,先理清整体思路;
对于题目要求我们要注意利用技巧减少时间耗时,如题目中利用缓存技巧;
设计树形数据结构时比起O(n) 用map 可以O(logn) 来找子目录;

注意:复制粘贴是原罪,即使指示重复的几行代码,负值粘贴过去就很有可能导致有些地方没改出错,又很难找出来。。。


代码:

#define _CRT_SECURE_NO_DEPRECATE 
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<map>
#include<string.h>
using namespace std;
char tms[20];//用于字符串输入

struct Directory;

struct command
{
	const string CMD_NAMES[7] = { "MKDIR","RM","CD","SZ","LS","TREE","UNDO" };
	int type;
	string argument;
	Directory* target_dir;

	command(string& t)
	{
		for (int i = 0; i < 7; i++)if (t == CMD_NAMES[i])type = i;
		if (type < 3)  //表示还需要第二个参数
		{
			scanf("%s", tms);
			argument = tms;
		}
	}
};


struct Directory
{
	string name;    //代表当前目录名字
	map<string, Directory*>children;  //便于直接找到
	Directory* parent;   //为了便于回溯到上一个目录处
	int subtreeSize;    //为了sz指令的方便
	vector<string>* tenDescend;
	bool update;

	Directory(string _name, Directory* _parent)
	{
		name = _name;
		parent = _parent;
		subtreeSize = 1;
		update = true;
		tenDescend = new vector<string>;
	}

	Directory* makedir(string &x);
	Directory* getchild(string& x);
	Directory* rm(string &x);
	Directory* cd(string &x);
	void maintain(int x);
	void ls();
	void sz()
	{
		printf("%d\n", subtreeSize);
	};
	void tree();
	Directory* addchild(Directory* x);
	void treeall(vector<string>* x);
	void treeFirstFive(int n, vector<string>* x);
	void treeLastFive(int n, vector<string>* x);
	
};


Directory* Directory::getchild(string& x)
{
	map<string, Directory*>::iterator iter = children.find(x);
	if (iter == children.end())return NULL;//找不到gg
	else
		return iter->second;
}

Directory* Directory::cd(string& x)
{
	if (x == "..")
		return parent;
	else return getchild(x);
}

Directory* Directory::makedir(string& x)
{
	map<string, Directory*>::iterator iter = children.find(x);
	if (iter != children.end())return NULL;//找得到gg
	Directory* te= new Directory(x, this);
	children[x] = te;
	maintain(1);
	return te;
}

Directory* Directory::addchild(Directory* x)//返回增加的目录
{
	map<string, Directory*>::iterator iter = children.find(x->name);
	if (iter != children.end())return NULL;//找得到gg
	else children[x->name] = x;
	maintain(1 * x->subtreeSize);
	return x;
}

Directory* Directory::rm(string& x)//返回已删除的目录
{
	map<string, Directory*>::iterator iter = children.find(x);
	if (iter == children.end())return NULL;//找不到gg
	maintain(-1 * iter->second->subtreeSize);
	Directory* temptt = iter->second;
	children.erase(iter);
	return temptt;
}

void Directory::maintain(int del)
{
	update = true;
	subtreeSize += del;
	if (parent != NULL)parent->maintain(del);
}

void Directory::ls()
{
	int size = children.size();
	if (size == 0)printf("EMPTY\n");
	else
	{
		if (size <= 10)
		{
			map<string, Directory*>::iterator iter = children.begin();
			for (; iter != children.end(); iter++)
			{
				printf("%s\n", iter->first.c_str());
			}
		}
		else
		{ 
			map<string, Directory*>::iterator iter = children.begin();
			for(int pl = 0;pl<5;pl++,iter++)
				printf("%s\n", iter->first.c_str());
			printf("...\n");
			iter = children.end();
			for (int pl = 0; pl < 5; pl++)iter--;
			for (int pl = 0; pl < 5; pl++, iter++)
				printf("%s\n", iter->first.c_str());
		}
	}
}

void Directory::tree() 
{
	if (subtreeSize == 1)
	{
			printf("EMPTY\n");
	}
	else
	{
		if (subtreeSize <= 10)
		{
			if (update)//如果已经有过更新重新遍历
			{
				tenDescend->clear();
				treeall(tenDescend);
				update = false;
			}
			int sz = tenDescend->size();
			for (int i = 0; i < sz; i++)
			{
				printf("%s\n", tenDescend->at(i).c_str());
			}
		}
		else {
			if (update)
			{
				tenDescend->clear();
				treeFirstFive(5,tenDescend);
				treeLastFive(5, tenDescend);
				update = false;
			}
			for (int i = 0; i < 5; i++)
			{
				printf("%s\n", tenDescend->at(i).c_str());
			}
			printf("...\n");
			for (int i = 9; i >= 5; i--)
			{
				printf("%s\n", tenDescend->at(i).c_str());
			}
		}
	}
}

void Directory::treeall(vector<string>* x)
{
	x->push_back(name);
	for (map<string, Directory*>::iterator iter = children.begin(); iter != children.end(); iter++)
	{
		iter->second->treeall(x);
	}
}

void Directory::treeFirstFive(int n, vector<string>* x)
{
	x->push_back(name);
	if (--n == 0)return;

	int size = children.size();
	map<string, Directory*>::iterator it = children.begin();

	while (size--)
	{
		int sizet = it->second->subtreeSize;
		if (sizet >= n)  //第一个孩子子树就已经满足了取前五个的条件
		{
			it->second->treeFirstFive(n, x);
			return;
		}
		else
		{
			it->second->treeFirstFive(sizet, x);
			n -= sizet;
		}
		it++;//去第二个孩子子树
	}
}

void Directory::treeLastFive(int n, vector<string>* x)
{
	int size = children.size();
	map<string, Directory*>::iterator it = children.end();//都是从最后一个开始
	while (size--)
	{
		it--;//到达最后一个
		int sizet = it->second->subtreeSize;
		if (sizet >= n)  //第一个孩子子树就已经满足了取前五个的条件
		{
			it->second->treeLastFive(n, x);
			return;
		}
		else
		{
			it->second->treeLastFive(sizet, x);
			n -= sizet;
		}
	}
	x->push_back(name);//最后一个先加入
}

void solve()
{
	long long n;
	scanf("%lld", &n);
	Directory* now = new Directory("root", NULL);
	vector<command*>cmdlist;
	for (int i = 0; i < n; i++)
	{
		scanf("%s", tms);
		string x = tms;
		command* cmd = new command(x);
		switch (cmd->type)
		{
		case 0:
		{	
			cmd->target_dir = now->makedir(cmd->argument);
			if (cmd->target_dir == NULL)printf("ERR\n");
			else
			{
				printf("OK\n");
				cmdlist.push_back(cmd);
			}
			break; 
		}
		case 1:
		{
			cmd->target_dir = now->rm(cmd->argument); 
			if (cmd->target_dir == NULL)printf("ERR\n");
			else
			{
				printf("OK\n");
				cmdlist.push_back(cmd);
			}
			break; }
		case 2: {
			Directory*te = now->cd(cmd->argument);
			if(te == NULL)printf("ERR\n");
			else {
				printf("OK\n");
				cmd->target_dir = now;
				now = te;
				cmdlist.push_back(cmd);
			}
			break; }
		case 3:now->sz(); break;
		case 4:now->ls(); break;
		case 5:now->tree(); break;
		case 6: {
			bool judge = false;
			if(!cmdlist.empty())
			{
				cmd = cmdlist.back(); cmdlist.pop_back();
				switch (cmd->type)
				{
				case 0:  //undo makedir
					if (now->rm(cmd->target_dir->name) != NULL)judge = true; break;
				case 1:  //undo rm
					if (now->addchild(cmd->target_dir) != NULL)judge = true; break;
				case 2: //undo cd
					now = cmd->target_dir; judge = true; break;
				default:
					break;
				}
			}
			if (judge)printf("OK\n"); else printf("ERR\n");
		}
		default:
			break;
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T-- != 0)
	{
		solve();
	}

}




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

A - 咕咕东的目录管理器 的相关文章

  • CentOS 8.0 安装 PostgreSQL12

    CentOS 8 0 基于最小包安装 xff0c 此后需要安装PostgreSQL12 1 安装源 dnf install https download postgresql org pub repos yum reporpms EL 8
  • 树莓派4配置USB启动-解决wlan0不识别问题

    参考了文章https blog csdn net nanhantianyi article details 106542616 基于RaspiOS lite 2021 1 11 成功升级了Pi4的eeprom 制作并实现了USB 2 0硬盘
  • 解决Manjaro内核升级失败无法启动问题一例

    这两天升级了manjaro 5 10 13 内核过程中 xff0c 一台Asus N43的老本出现了各种诡异问题 xff0c 记录一下 xff1a 1 目录链接丢失 参照其他机器重建了lib sbin等目录链接 2 新内核无法启动 将gru
  • Sever2019安装OpenSSH问题1例

    从github下载的openssh for windows版本 xff0c 执行ps脚本安装 xff0c ssh登录正常 xff0c winscp反复报错 无法初始化SFTP协议 主机是SFTP服务器吗 xff1f 查阅了各种资料 xff0
  • Excel2013 打开文档 显示 内存或磁盘空间不足 无法再次打开或保存 的问题

    Office 2013 问题描述 xff1a 我在网上下载了一个 excel 2003 的文件 xff0c 双击打开 xff0c Excel 提示 xff1a 内存或磁盘空间不足 excel 无法再次打开或保存 解决方案 xff1a 右键下
  • Oracle安装问题INS-30131解决方法

    Win 8下安装Oracle 11 2 0 4遇到了错误INS 30131 Google搜索发现多说都说是共享文件夹问题 xff0c 按方法试验无效 于是想删除临时文件再重新安装一次 xff0c 发现oraremexecservice目录无
  • 去掉微信浏览器里的放大缩小按钮

    lt meta http equiv 61 34 Content Type 34 content 61 34 text html charset 61 utf 8 34 gt lt meta name 61 34 viewport 34 c
  • 清除SSH秘钥的命令

    重新安装了openmediavault之后在连接就是这样 xff0c 具体的原因是因为主机保存了以前的秘钥 PS C Users qs gt ssh root 64 10 11 12 2 64 64 64 64 64 64 64 64 64
  • HR-XML(可扩展人力资源标准)简介

    HR XML xff08 可扩展人力资源标准 xff09 简介 Flyspace flyspace 64 x263 net 2003 年 12 月 12 日 标准出处 xff1a http www hr xml org 标准简介 xff1a
  • 解决System进程占用80端口的问题

    1 IIS占用80端口 用如下方法可以解决System进程占用80端口的问题 xff1a 打开RegEdit 找到HKEY LOCAL MACHINE SYSTEM CurrentControlSet Services HTTP 找到一个D
  • Win 7, Server 2008 R2最大线程数限制

    最近在做压力测试时发现Win 7 和 Server 2008 R2 系统内线程数设为1500则无法创建线程池 xff0c 深入分析发现32位和64位程序存在很大性能差异 最大线程数 xff1a 32bit xff1a 1450 64bit
  • 算法|找出数组的最大公约数

    力扣第255场周赛题目 刷题链接 https leetcode cn com problems find greatest common divisor of array 题目描述 给你一个整数数组 nums xff0c 返回数组中最大数和
  • 结构体对齐规则

    结构体对齐规则 xff1a 1 第一个成员在于结构体变量偏移量为0的地址处 2 其他成员变量要对齐到某个数字 xff08 对齐数 xff09 的整数倍的地址处 对齐数 61 编译器默认的一个对齐数 与 该成员大小的 较小值 3 结构体总大小
  • Snapper转换器的捕捉类型

    原文发布时间 xff1a 2014 09 24 作者 xff1a Tenniwdy 在数据处理中Snapper转换器的作用是很强大的 xff0c 它的各类捕捉类型能针对不同的需求对数据进行处理 在FME Desktop 2014版本中新增了
  • STM32 4x4矩阵键盘初始化及实现多位输入

    目的 xff1a 实现矩阵键盘的多位数据输入 这里以两位数据为例 引脚初始化PC0 PC7 void Key Config GPIO InitTypeDef GPIO InitStructure RCC APB2PeriphClockCmd
  • CSP 202206 题解:归一化处理,寻宝大冒险,角色授权,光线追踪,PS无限版

    试题内容请前往CCF官网查看 xff1a CCF CSP计算机软件能力认证考试 http 118 190 20 162 home page 阅读本题解前 xff0c 您应当了解下列知识 xff1a 线段树 教程C 43 43 标准库 xff
  • 在 VirtualBox 中构建 Debian11 虚拟电脑

    文章目录 前言一 准备工作和Debian简介二 新建虚拟电脑三 安装 Debian11四 Debian11系统环境配置配置光盘软件镜像源配置国内镜像软件源控制台鼠标支持 安装虚拟机增强功能SSH 接入国际化和本地化配置网卡 结语 前言 介绍
  • 【华为机试真题 Python】 放苹果

    目录 题目描述 输入 输出 示例 参考代码 题目描述 把m个同样的苹果放在n个同样的盘子里 允许有的盘子空着不放 问共有多少种不同的分法 注意 如果有7个苹果和3个盘子 5 1 1 和 1 5 1 被视为是同一种分法 数据范围 0 m 10
  • keil5 显示 No target connected

    keil5 显示 No target connected 第一 xff0c 确认上电是否正常 xff0c 板子上有电源指示灯 xff1b 就是那个红色的指示灯 第二 xff1a 长按核心板上的复位键不要松开 找到Debug xff0c 确认
  • Debian系统安装中文包

    相对于Ubuntu系统 xff0c debian系统性对来说较为原始 xff0c 不能像Ubuntu一样一键设定为中文 xff0c 这样就必须自行设定 xff1a 1 安装aptitude xff1a sudo apt span class

随机推荐

  • 解决Linux(Ubuntu)系统下复制粘贴文件权限不够的问题

    首先是ctrl 43 alt 43 t 打开一个终端 运行命令 sudo nautilus 就可以打开一个具有管理员权限的文件管理器 xff0c 然后就可以在不切换到管理员的条件下拷贝文件
  • 解决开机出现“CLIENT MAC ADDR”的问题

    开机自检后 xff0c 系统会出现网卡配置的提示 xff0c 此时按Shift 43 F10组合键可进入配置页面 xff0c 如果不按该组合键 xff0c 几秒后则跳入下一页面 xff0c 这里会停留一段时间 xff0c 一般是一二十秒的样
  • iOS之性能优化·提高App的编译速度

    一 前言 经过多年的开发和迭代 xff0c 我相信很多的 iOS 项目代码已经达到几十万行甚至上百万行的规模 xff0c 所使用的 Pod 库的数量可以达到几十个甚至上百个 xff0c App Store 安装包也变得越来越大 xff0c
  • iOS之性能优化·优化App界面的渲染与流畅度

    一 界面渲染流程 渲染流程分析 计算机中的显示过程通常是通过 CPU GPU 显示器协同工作来将图片显示到屏幕上 xff0c 如下图所示 xff1a 苹果为了解决图片撕裂的问题使用了 VSync 43 双缓冲区的形式 xff0c 就是显示器
  • 图像处理:傅里叶变换

    0 引言 在之前的博客 图像增强 xff0c 傅里叶变换 xff08 OpenCV 中都有用到过傅里叶变换 xff0c 但一直都不是特别理解 xff0c 现系统地学习一下 先来看一个视频 傅里叶级数与傅立叶变换 xff0c 我们了解到任何周
  • 从键盘输入10个整数,判断并输出10个数中的最大值和平均值

    include lt graphics h gt include lt conio h gt include lt stdio h gt int main int a 61 0 b 61 0 c 61 0 i 61 1 n max 61 0
  • ubuntu虚拟机忘记开机密码,重置密码

    有时我们会忘记ubuntu虚拟机的开机密码 xff0c 这是候需要我们重置密码 xff0c 步骤如下 xff1a 1 打开虚拟机 xff0c 在虚拟机启动界面出现时 xff0c 鼠标点击虚拟机启动界面 xff0c 将键盘输入定向到虚拟机 x
  • 结构体数组操作+文件读写

    一 1 声明了该结构体就声明了结构体内所有成员 include lt stdio h gt typedef struct stuInfo char name int age int num Student int main int argc
  • CEF中JavaScript与C++交互

    在CEF里 xff0c JS和Native xff08 C C 43 43 xff09 代码可以很方便的交互 xff0c 这里https bitbucket org chromiumembedded cef wiki JavaScriptI
  • 阿里云网盘内测网址

    阿里云Teambition网盘内测申请地址 这个网盘还没有开放 xff0c 想要体验的话可以申请 xff0c 通过后 xff0c 获得体验资格 网址 xff1a https form teambition net f CjQetM x fi
  • Python 创建安装包

    Version usr bin env python3 coding utf 8 64 Author forward huan 64 Time 2022 07 14 23 05 64 Description import json impo
  • IOS UITableViewCell高度自适应的那些事

    好啦 xff0c 这是一个老生常谈的问题 真的 xff0c 有时候把人气得想去搞安卓 xff0c 安卓就没得这码子事 xff5e 方案有很多 xff0c 我这里提供三种方案 其实每种自适应高度的方法都有比较适合自己的情景 xff0c 比如c
  • Sublime Text 最新注册码

    Sublime Text 最新注册码 Sublime 更新后 xff0c 很多验证码都失效了 收集了一些在 2017 09 14 测试有效的注册码 xff0c 适用于 xff1a Sublime Text 2 3 xff0c Build 2
  • 群晖NAS变成TimeMachine时间机器完成Mac备份

    如果有一台群晖Nas xff0c 那么我们可以很方便的利用他完成Mac系统的自动备份 我的群晖在路由器后面 xff0c 所以当我不再家的时候备份 xff0c 则需要使用vpn连接到群晖 接下来让我们实践出真知吧 1 在群晖nas中设置一个同
  • 如何生成ssh key,以及repo init 遇到的无法检查签名:找不到公钥 问题

    repo init 遇到 无法检查签名 找不到公钥 的问题 源文章 xff1a http blog csdn net njuitjf article details 38386941 方法一 xff1a 出现此问题是repo版本不对的问题
  • 选数问题 Gym - 270437C

    题意 xff1a 给定n个正整数 xff0c 从中选取K个数 xff0c 保证这K个数的和是S 求有多少种选择的方法 Input 第一行输入一个整数T T lt 61 100 xff0c 表示有T个测试样例 对于每个例子 xff0c 有两行
  • 掌握魔法的东东II Gym - 101510B

    题意 xff1a 从瑞神家打牌回来后 xff0c 东东痛定思痛 xff0c 决定苦练牌技 xff0c 终成赌神 xff01 东东有 A B 张扑克牌 每张扑克牌有一个大小 整数 xff0c 记为a xff0c 范围区间是 0 到 A 1 x
  • 传递闭包 Floyd算法

    题意 xff1a 众所周知 xff0c TT 有一只魔法猫 这一天 xff0c TT 正在专心致志地玩 猫和老鼠 游戏 xff0c 然而比赛还没开始 xff0c 聪明的魔法猫便告诉了 TT 比赛的最终结果 TT 非常诧异 xff0c 不仅诧
  • csp m2 咕咕东的奇妙序列 二分

    题意 xff1a 题目描述 咕咕东 正在上可怕的复变函数 xff0c 但对于稳拿A Plus的 咕咕东 来说 xff0c 她早已不再听课 xff0c 此时她在睡梦中 突然想到了一个奇怪的无限序列 xff1a 112123123412345
  • A - 咕咕东的目录管理器

    题意 xff1a 样例输入 xff1a span class token number 1 span span class token number 22 span MKDIR dira CD dirb CD dira MKDIR a MK