程设第九周

第一题

题意

咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 —— 这工程量太大了,所以他定了一个小目标,从实现一个目录管理器开始。前些日子,东东的电脑终于因为过度收到宇宙射线的影响而宕机,无法写代码。他的好友TT正忙着在B站看猫片,另一位好友瑞神正忙着打守望先锋。现在只有你能帮助东东!

初始时,咕咕东的硬盘是空的,命令行的当前目录为根目录 root。

目录管理器可以理解为要维护一棵有根树结构,每个目录的儿子必须保持字典序。
在这里插入图片描述

现在咕咕东可以在命令行下执行以下表格中描述的命令:

在这里插入图片描述

输入

输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);

每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);

每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。

输出

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

时空限制

Time limit 6000 ms

Memory limit 1048576 kB

思路

对于一组数据:

设置结构体cmd用来存储指令,包括指令类型,进行操作的目录s,位置olddir。

设置结构体dir用来存储节点,包括当前节点名字,父节点,子节点的map映射,以当前为根的子树的大小,更新标记,遍历数组,各种函数。

对于undo命令,因为要进行撤销,所以我们要对所有能执行的命令进行储存。

代码
#include<iostream>
#include<map>
#include<vector>

using namespace std;

string commands[7]={"MKDIR","RM","CD","SZ","LS","TREE","UNDO"};
struct dir
{
	string name;
	map<string,dir*> children;	
	dir *parent;
	int size;
	bool update;
	vector<string> ans;
	dir (string name,dir *parent)
	{
		size=1;
		this->name=name;
		this->parent=parent;
	}
public:
	dir* getchild(string s)	
	{
		map<string,dir*>::iterator it=children.find(s);
		if (it==children.end())
			return NULL;
		return it->second;
	}
	dir* mkdir(string s)
	{
		if (children.find(s)!=children.end())
			return NULL;
		dir *now=new dir(s,this);
		children[s]=now;
		maintain(1);
		return now;
	}
	dir* rm(string s)
	{
		map<string,dir*>::iterator it=children.find(s);
		if (it==children.end())
			return NULL;
		maintain(-it->second->size);
		children.erase(it);
		return it->second;
	}
	dir* cd(string s)
	{
		if (s=="..")
			return this->parent;
		return getchild(s);
	}
	void addchild(dir *child)
	{
		if (children.find(child->name)!=children.end())
			return;
		children[child->name]=child;	
		maintain(child->size);
		return;
	}
	void maintain(int sum)
	{
		update=true;
		size=size+sum;
		if (parent!=NULL)
			parent->maintain(sum);
	}
	void sz()
	{
		cout<<size<<endl; 
	}
	void ls()
	{
		int sum=children.size();
		if (sum==0)
		{
			cout<<"EMPTY"<<endl;
			return;
		}
		if (sum<=10)
		{
			map<string,dir*>::iterator it=children.begin();
			while (it!=children.end())
			{
				cout<<it->first<<endl;
				it++;
			}
		}
		else
		{
			map<string,dir*>::iterator it=children.begin();
			for (int i=0;i<5;i++)
			{ 
				cout<<it->first<<endl;
				it++;
			}
			cout<<"..."<<endl;
			it=children.end();
			for (int i=0;i<5;i++) 
				it--;
			for (int i=0;i<5;i++)
			{ 
				cout<<it->first<<endl;
				it++;
			}
		}
	}
	void tree()
	{
		if (size==1) 
		{
			cout<<"EMPTY"<<endl;
			return;
		}
		if(size<=10)
		{
			if (update)		//需要更新则更新 
			{
				ans.clear();
				treeall(&ans);
				update=false;
			}
			for(int i=0;i<size;i++)
				cout<<ans[i]<<endl;
		}
		else
		{
			if (update)
			{
				ans.clear();
				treel(5,&ans);
				treer(5,&ans);
				update=false;
			}
			for(int i=0;i<5;i++)
				cout<<ans[i]<<endl;
			cout<<"..."<<endl;
			for(int i=9;i>=5;i--)
				cout<<ans[i]<<endl;
		}
	}
private:
	void treeall(vector<string> *v)
	{
		v->push_back(name);
		map<string,dir*>::iterator it=children.begin();
		while (it!=children.end())
		{
			it->second->treeall(v);
			it++;
		}
	}
	void treel(int x,vector<string> *v)
	{
		v->push_back(name);
		x--;
		if (x==0) 
			return;
		int n=children.size();
		map<string,dir*>::iterator it=children.begin();
		while (n--)
		{
			int sum=it->second->size;
			if (sum>=x)
			{
				it->second->treel(x,v);
				return;
			}
			else
			{
				it->second->treel(sum,v);
				x=x-sum; 
			}
			it++;
		}
	}
	void treer(int x,vector<string> *v)	
	{
		int n=children.size();
		map<string,dir*>::iterator it=children.end();
		while (n--)
		{
			it--;
			int sum=it->second->size;
			if (sum>=x)
			{
				it->second->treer(x,v);
				return;
			}
			else
			{
				it->second->treer(sum,v);
				x=x-sum;
			}
		}
		v->push_back(name);
	}
};

struct cmd
{
	int type;
	string s;
	dir* olddir;
	cmd(string temp)
	{
		for(int i=0;i<7;i++)
			if(commands[i]==temp)
			{
				type=i;
				if (i<3)
					cin>>s;
			}
	}	
};

void solve()
{
	dir *now=new dir("root",NULL); 
	vector<cmd*> cmdlist;
	string s;
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>s;
		cmd *c=new cmd(s);
		if (c->type==0)
		{
			c->olddir=now->mkdir(c->s);
			if (c->olddir==NULL)
				cout<<"ERR"<<endl;
			else
			{
				cout<<"OK"<<endl; 
				cmdlist.push_back(c);
			}
		} 	
		if (c->type==1)
		{
			c->olddir=now->rm(c->s);
			if(c->olddir==NULL)
				cout<<"ERR"<<endl;
			else
			{
				cout<<"OK"<<endl; 
				cmdlist.push_back(c);
			}
		}
		if (c->type==2)
		{
			dir *newNow=now->cd(c->s);
			if (newNow==NULL)
				cout<<"ERR"<<endl;
			else
			{
				cout<<"OK"<<endl;
				c->olddir=now;
				now=newNow;
				cmdlist.push_back(c);	
			}
		}	
		if (c->type==3)
			now->sz();
		if (c->type==4)
			now->ls();
		if (c->type==5)
			now->tree();
		if (c->type==6)
		{
			if (!cmdlist.empty())
			{
				c=cmdlist.back();
				if (c->type==0)
					dir *temp=now->rm(c->s);
				if (c->type==1)
					now->addchild(c->olddir);
				if (c->type==2)
					now=c->olddir;
				cout<<"OK"<<endl; 
			}
			else
				cout<<"ERR"<<endl;
		}  
	}
}
int main()
{
	int t;
	cin>>t;
	for(int i=0;i<t;i++)
		solve();
	
	return 0;
} 

第二题

题意

最近,东东沉迷于打牌。所以他找到 HRZ、ZJM 等人和他一起打牌。由于人数众多,东东稍微修改了亿下游戏规则:

所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K 分别指代 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13。
每个玩家抽得 5 张扑克牌,组成一手牌!(每种扑克牌的张数是无限的,你不用担心,东东家里有无数副扑克牌)

理所当然地,一手牌是有不同类型,并且有大小之分的。

举个栗子,现在东东的 “一手牌”(记为 α),瑞神的 “一手牌”(记为 β),要么 α > β,要么 α < β,要么 α = β。

那么这两个 “一手牌”,如何进行比较大小呢?首先对于不同类型的一手牌,其值的大小即下面的标号;对于同类型的一手牌,根据组成这手牌的 5 张牌不同,其值不同。下面依次列举了这手牌的形成规则:

大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。

对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 "对子" 的大小,如果 α 和 β 的 "对子" 大小相等,那么比较剩下 3 张牌的总和。

两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。

三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 "三个",比较这个 "三个" 的大小,如果 α 和 β 的 "三个" 大小相等,那么比较剩下 2 张牌的总和。

三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 "三带二",先比较它们的 "三个" 的大小,如果相等,再比较 "对子" 的大小。

炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 "炸弹",比较 "炸弹" 的大小,如果相等,比较剩下那张牌的大小。

顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 "顺子",直接比较两个顺子的最大值。

龙顺:5 张牌分别为 10、J、Q、K、A。

作为一个称职的魔法师,东东得知了全场人手里 5 张牌的情况。他现在要输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。

不料,此时一束宇宙射线扫过,为了躲避宇宙射线,东东慌乱中清空了他脑中的 Cache。请你告诉东东,全场人的排名

输入

输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。

输出

对于每组测试数据,输出 n 行,即这次全场人的排名。

思路

比较大小,一共只有八种情况,所以我们直接处理手牌是哪种情况,设第x种,然后给这个手牌一个权重,首先设置一个大数,1e7,然后权重就是1e7x,然后对于同一种手牌,我们的比较最多也只用三次比较,所以第一次10000+第二次*100+第三次构成我们只一种手牌的权重。

举个例子,4499K,首先这是两对,属于第三种,sum=1e73+910000+4*100+13,这样我们对所有的手牌处理之后直接sort,逆序输出即可。

代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define ll 10000000

using namespace std;

struct data
{
	string name;
	int sum;
	bool operator < (const data & x)
	{ 
		return (sum!=x.sum)?(sum<x.sum):(name>x.name);
	}
};

int main()
{
	int n,o,tot;
	string s;
	data a[100010];
	int p[100];
	int x[100],y[100];
	while (scanf("%d",&n)!=EOF)
	{
		for (int j=0;j<n;j++)
		{
			cin>>a[j].name;
			cin>>s;
			int l=s.length();
			for (int i=0;i<20;i++)
				p[i]=0;
			for (int i=0;i<l;i++)
			{
				if (s[i]>'1' && s[i]<='9')
					p[s[i]-'0']++;
				if (s[i]=='A')
					p[1]++;
				if (s[i]=='J')
					p[11]++;
				if (s[i]=='Q')
					p[12]++;
				if (s[i]=='K')
					p[13]++;
				if (s[i]=='1')
				{
					p[10]++;
				}
			}
			tot=0;
			for (int i=1;i<=13;i++)
				if (p[i]!=0)
				{
					x[tot]=i;
					y[tot]=p[i];
					tot++;
				}
			if (tot==5)
			{
				if (x[0]==1 && x[1]==10)
					a[j].sum=ll*8;
				o=0;
				for (int i=1;i<tot;i++)
					if (x[i]!=x[i-1]+1)
						o=1;
				if (o==0)
					a[j].sum=ll*7+x[0];
				else
					for (int i=0;i<tot;i++)
						a[j].sum+=x[i];
			}
			if (tot==4)
			{
				for (int i=0;i<tot;i++)
					if (y[i]==2)
						o=x[i];
				a[j].sum=ll*2+o*10000;
				for (int i=0;i<tot;i++)
					if (y[i]==1)
						a[j].sum+=x[i];
			}
			if (tot==3)
			{
				for (int i=0;i<tot;i++)
					if (y[i]==1)
						a[j].sum+=x[i];
				for (int i=0;i<tot;i++)
					if (y[i]==3)
						a[j].sum+=ll*4+x[i]*10000;
				o=0;
				for (int i=0;i<tot;i++)
					if (y[i]==2)
					{
						if (o==0)
						{
							a[j].sum+=ll*3+x[i]*100;
							o++;
						}
						else 
							a[j].sum+=x[i]*10000;
					}
			}
			if (tot==2)
			{
				for (int i=0;i<tot;i++)
				{
					if (y[i]==1)
						a[j].sum+=x[i];
					if (y[i]==2)
						a[j].sum+=x[i]*100;
					if (y[i]==3)
						a[j].sum+=ll*5+x[i]*10000;
					if (y[i]==4)
						a[j].sum+=ll*6+x[i]*10000;
				}
			}
			if (tot==1)
				a[j].sum=x[0]*5; 
		}
		sort(a,a+n);
		for (int i=n-1;i>=0;i--)
			cout<<a[i].name<<endl;
		for (int i=0;i<n;i++)
			a[i].sum=0;
	}
} 

第三题

题意

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

思路

mx就是最大值+y,mn就是先将人从当前坐的最少的长凳上补,补到max,所有的长凳都补到max之后若还有剩余,则平均分摊,否则就是max。

代码
#include<iostream>

using namespace std;

int main()
{
	int n,x,y,z,sum,min,max;
	cin>>n>>y;
	sum=0;
	max=0;
	min=100010;
	for (int i=0;i<n;i++)
	{
		cin>>x;
		if (x>max)
			max=x;
		if (x<min)
			min=x;
		sum=sum+x;
	}
	min=max;
	while (min*n<sum+y)
		min++;
	cout<<min<<" "<<max+y<<endl;
	
	return 0;
} 
数据中心机房是现代信息技术的核心设施,它承载着企业的重要数据和服务,因此,其基础设计与规划至关重要。在制定这样的方案时,需要考虑的因素繁多,包括但不限于以下几点: 1. **容量规划**:必须根据业务需求预测未来几年的数据处理和存储需求,合理规划机房的规模和设备容量。这涉及到服务器的数量、存储设备的容量以及网络带宽的需求等。 2. **电力供应**:数据中心是能源消耗大户,因此电力供应设计是关键。要考虑不间断电源(UPS)、备用发电机的容量,以及高效节能的电力分配系统,确保电力的稳定供应并降低能耗。 3. **冷却系统**:由于设备密集运行,散热问题不容忽视。合理的空调布局和冷却系统设计可以有效控制机房温度,避免设备过热引发故障。 4. **物理安全**:包括防火、防盗、防震、防潮等措施。需要设计防火分区、安装烟雾探测和自动灭火系统,设置访问控制系统,确保只有授权人员能进入。 5. **网络架构**:规划高速、稳定、冗余的网络架构,考虑使用光纤、以太网等技术,构建层次化网络,保证数据传输的高效性和安全性。 6. **运维管理**:设计易于管理和维护的IT基础设施,例如模块化设计便于扩展,集中监控系统可以实时查看设备状态,及时发现并解决问题。 7. **绿色数据中心**:随着环保意识的提升,绿色数据中心成为趋势。采用节能设备,利用自然冷源,以及优化能源管理策略,实现低能耗和低碳排放。 8. **灾难恢复**:考虑备份和恢复策略,建立异地灾备中心,确保在主数据中心发生故障时,业务能够快速恢复。 9. **法规遵从**:需遵循国家和地区的相关法律法规,如信息安全、数据保护和环境保护等,确保数据中心的合法运营。 10. **扩展性**:设计时应考虑到未来的业务发展和技术进步,保证机房有充足的扩展空间和升级能力。 技术创新在数据中心机房基础设计及规划方案中扮演了重要角色。例如,采用虚拟化技术可以提高硬件资源利用率,软件定义网络(SDN)提供更灵活的网络管理,人工智能和机器学习则有助于优化能源管理和故障预测。 总结来,一个完整且高效的数据中心机房设计及规划方案,不仅需要满足当前的技术需求和业务目标,还需要具备前瞻性和可持续性,以适应快速变化的IT环境和未来可能的技术革新。同时,也要注重经济效益,平衡投资成本与长期运营成本,实现数据中心的高效、安全和绿色运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值