week9-作业

这篇博客讨论了两个编程题目,一个是关于公园长凳人数的最大最小值问题,另一个涉及目录管理器的实现。公园长凳问题通过遍历和简单的数学计算得出答案,而目录管理器的实现涉及目录的创建、删除、移动和查询操作,需要设计高效的数据结构和算法来处理。
摘要由CSDN通过智能技术生成

先从C题写好了~ C题最简单

C - 签到题

题意:

SDUQD 旁边的滨海公园有 x 条长凳。第 i 个长凳上坐着 a_i 个人。这时候又有 y 个人将来到公园,他们将选择坐在某些公园中的长凳上,那么当这 y 个人坐下后,记k = 所有椅子上的人数的最大值,那么k可能的最大值mx和最小值mn分别是多少。
Input
第一行包含一个整数 x (1 <= x <= 100) 表示公园中长椅的数目
第二行包含一个整数 y (1 <= y <= 1000) 表示有 y 个人来到公园
接下来 x 个整数 a_i (1<=a_i<=100),表示初始时公园长椅上坐着的人数
Output
输出 mn 和 mx
Input Example
3
7
1 6 1
Output Example
6 13

思路:

这道题肯定不能将所有数组找出来
而是用最简单的思路
mx最好找,找到初始时椅子上人数的最大值直接加上y就是k的最大值。
mn找法:遍历所有用y减去(椅子上人数的最大值-ai),中间判断y是否小于等于0,若小于等于,就停止遍历。遍历完后判断剩余的y除以x的余数是否等于0,若等于mn=初始时椅子上人数最大值+y/x,不等于则mn = mx1 + (y / x) + 1。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int x, a[100000], y;
int mn, mx1=0,mx;
int main()
{
   
	cin >> x >> y;
	for (int i = 0; i < x; i++)
		cin >> a[i];
	for (int i = 0; i < x; i++)
		mx1 = max(mx1, a[i]); 
	mx = mx1 + y;
	for (int i = 0; i < x; i++)
	{
   
		y = y - (mx1 - a[i]);
		if (y <= 0)
		{
   
			mn = mx1;
			break;
		}
	}
	if (y > 0)
	{
   
		if (y % x == 0)
		{
   
			mn = mx1 + (y / x);
		}
		else mn = mx1 + (y / x) + 1;
	}
	cout << mn << " "<<mx << endl;
	return 0;
}

A-咕咕东的目录管理器

题意:

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

命令 类型 实现 说明
MKDIR s 操作 在当前目录下创建一个子目录 s,s 是一个字符串 创建成功输出 “OK”;若当前目录下已有该子目录则输出 “ERR”
RM s 操作 在当前目录下删除子目录 s,s 是一个字符串 删除成功输出 “OK”;若当前目录下该子目录不存在则输出 “ERR”
CD s 操作 进入一个子目录 s,s 是一个字符串(执行后,当前目录可能会改变) 进入成功输出 “OK”;若当前目录下该子目录不存在则输出 “ERR”
特殊地,若 s 等于 “…” 则表示返回上级目录,同理,返回成功输出 “OK”,返回失败(当前目录已是根目录没有上级目录)则输出 “ERR”
SZ 询问 输出当前目录的大小 也即输出 1+当前目录的子目录数
LS 询问 输出多行表示当前目录的 “直接子目录” 名 若没有子目录,则输出 “EMPTY”;若子目录数属于 [1,10] 则全部输出;若子目录数大于 10,则输出前 5 个,再输出一行 “…”,输出后 5 个。
TREE 询问 输出多行表示以当前目录为根的子树的前序遍历结果
在这里插入图片描述
UNDO 特殊 撤销操作 撤销最近一个 “成功执行” 的操作(即MKDIR或RM或CD)的影响,撤销成功输出 “OK” 失败或者没有操作用于撤销则输出 “ERR”
输入
输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);
每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);
每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。
输出
每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。

思路:

因为操作比较多,为了实现这些操作,有两个结构体,一个用来存放指令command,一个用来存放目录的信息catalogtree.
command存放:操作类型,不同的操作有不同的操作数。
catalogtree存放:目录的名字,目录的子目录,目录上一级,目录大小
所有的操作指令都放在一个vector数组里。
MKDIR新建目录:检查是否存在,存在即建立,更新目录大小
RM删除目录:先检查当前目录下是否已经存在要删除的目录,存在就删除
CD 用一个变量n若是参数时“. .”,则要判断父节点是不是空,若是其他则要判断有没有这个子目录名,成功进入的操作要记录在操作数组里ow,记录当前位置.
SZ操作 直接输出结构体里表示目录数目
LS操作 根据每个结点map的映射数目,直接孩子目录数目<=0则直接输出,否则输出前五个和后五个。
UNDO撤回操作:从之前的指令数组中取出指令
TREE输出子树 存储一下答案,并且标记一下是否被更新过
节点数远少于TREE操作数,指不定还有重复询问,对于目录相同期间问过的相同问题,理应只有一次是计算过程。对每个结点都有一个v数组和b数组用来存储前序遍历的前几个点,和后序的几个点。

#include<iostream>
#include<map>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define f(i,a,b) for(int i=a;i<b;i++)
const string cdname[] = {
    "MKDIR","RM","CD","SZ","LS","TREE","UNDO" };
struct command {
   
	int option = -1;
	string type;
	string operand;
	command() {
   }

	void init(string s)
	{
   
		type = s;
		f(i,0,7) 
		{
   
			if (s == cdname[i]) 
			{
   
				option = i;
				if (i < 3)
					cin >> operand;
				break;
			}
		}
	}
};

struct  catalogtree
{
   
	string name;
	map<string, int> ch;
	bool ide;
	int parent;
	int idesize;//目录的大小
	
	vector<string>v, b;

	catalogtree() {
   }
	void init(string n, int p) {
   
		ide = 0;
		parent = p;
		idesize = 1;
		name = n;
		v.clear();
		b.clear();
		ch.clear();
	}
};

catalogtree c[100100];
int cnt, now;
command cd;
vector<pair<string, pair<int, int> > >op;

void initialize() 
{
   
	cnt = 0;
	now = 0;
	op.clear();
	c[0].init("root", -1);
}

void update_size(int x, int num) 
{
   
	while (x != -1) {
   
		c[x].ide = 0;
		c[x].idesize = c[x].idesize + num;
		x = c[x].parent;
	}
}

void make_newloge(string s, int par) 
{
   
	cnt++;
	c[cnt].init(s, par);
	c[par].ch[s] = cnt;	
}


void mkdir() 
{
   

	if (c[now].ch.count(cd.operand)) 
	{
   
		cout << "ERR" << endl;
	}
	else 
	{
   
		make_newloge(cd.operand, now);
		op.push_back(make_pair("MKDIR", make_pair(now, cnt)));
		update_size(now, 1);
		cout << "OK" << endl;
	}
}

void rm() 
{
   
	if (!c[now].ch.count(cd.operand)) 
	{
   
		cout << "ERR" << endl;
	}
	else 
	{
   
		int bj = c[now].ch[cd.operand];
		update_size(now, -c[bj].idesize);
		op.push_back(make_pair("RM", make_pair(now, bj)));
		c[now].ch.erase(c[bj].name);
		cout << "OK" << endl;
	}
}


void cds() 
{
   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值