A - 咕咕东的目录管理器
问题描述
咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 —— 这工程量太大了,所以他定了一个小目标,从实现一个目录管理器开始。前些日子,东东的电脑终于因为过度收到宇宙射线的影响而宕机,无法写代码。他的好友TT正忙着在B站看猫片,另一位好友瑞神正忙着打守望先锋。现在只有你能帮助东东!
初始时,咕咕东的硬盘是空的,命令行的当前目录为根目录 root。
目录管理器可以理解为要维护一棵有根树结构,每个目录的儿子必须保持字典序。
现在咕咕东可以在命令行下执行以下表格中描述的命令:
输入
输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);
每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);
每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。
输出
每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。
时空限制
Time limit 6000 ms
Memory limit 1048576 kB
样例输入
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
解题思路
- 本题主要难在撤销操作和其他时间复杂度有要求的操作
- 因为每个目录的儿子必须保持字典序,插入一个排序一次会浪费时间,所以使用map<string,int>存储目录下的“儿子”,建立string到int的映射,自动排序。
- UNDO:只能撤销插入、删除、进入子目录。所以用vector储存,每次进行上述三种操作时把对应的操作插入vector;UNDO时取vector尾元素,得到进行的操作,插入边则删除它,删除边则恢复它,进入子目录则返回根目录。用point结构体储存操作名称、当前位置和操作的目录。
- SZ:如果每次都遍历一次所有的目录获得size,则每次查询的最大计算量即为树的最大规模,5000;最大查询次数为1e5-5000=9.5e4;最大计算量约为50001e520=1e10,超时。所以每次在每个节点增加一个变量sz,加上该节点后的size;输出"根节点"的sz即可。
- 用update函数更新size,需要从插入处往上更新,所以在节点中加入储存父节点的变量fa;根目录的父节点置为-1;
- TREE:如果每一次都遍历一次,得到结果,则每次的最大计算量即树的最大规模,5000;最大查询次数9.5e4,最大计算量约为50001e520=1e10,超时。所以利用懒更新的方法,将结果储存在数组中,并记录值是否更新过(是否进行过插入删除);每次调用该操作时更新过则重新遍历,未更新过则直接输出。
- MKDIR:搜索是否存在要插入的子目录,是则输出错误信息,不存在则对应位置插入即可。将该操作存入vector;调用update函数更新sz,并记录走过的节点为需要更新。
- RM:搜索要删除的子目录是否存在,不存在则输出错误信息,存在则删除对应的一条边即可(如果删除了对应节点,则该节点下面的所有子节点都没了,恢复十分困难);调用update函数更新sz,并记录走过的节点为需要更新。
- CD:进入子目录s(检验是否存在)或者返回上层目录(检验是否为根目录),储存操作为undo做准备,更新now的位置即可。
- LS:没有子目录则输出empty;利用map自带的迭代器,小于10个则全输出,大于则输出前五、后五个。
完整代码
#include <iostream>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
struct Directory
{
string name; //名称
map<string,int>mp; //后代的名称->编号,自动排序
int fa,sz; //父亲节点,子树的规模
vector<string> pre,bck; //存前序遍历的前后序列
bool tag; //记录是否被更新过
};
Directory node[200000];
//node[i]和map中的second相对应
int now; //当前节点
int idx; //最新节点
struct point //用于undo储存信息
{
string name; //操作名称
int now;
int next; //要操作的目录位置
};
vector<point> v;//记录可以进行undo的操作
void update(int id,int num) //更新size,即 id处的节点增加了num
{//id不到最头上
while(id!=-1)
{
node[id].tag=0;//标记为未改变
node[id].sz+=num;//加上num
id=node[id].fa;//往上走
}
}
void MKDIR(string &s) //在当前目录下创建一个子目录s
{
if(node[now].mp.count(s)==1) //存在节点
cout<<"ERR"<<endl;
else
{
node[now].mp.insert(pair<string,int>(s,idx));
update(now,1);
//在node[idx]创建新节点
node[idx].name=s;
node[idx].fa=now;
node[idx].sz=1;
node[idx].tag=0;//标记为需要重新遍历
node[idx].mp.clear();
node[idx].pre.clear();
node[idx].bck.clear();
//将操作放入undo的vector中
point p;
p.name="MKDIR",p.now=now,p.next=idx;
v.push_back(p);
idx++;
cout<<"OK"<<endl;
}
}
void RM(string &s) //在当前目录下删除子目录s
{
if(node[now].mp.count(s)==1) //存在节点
{
int indexOfS=node[now].mp[s];
node[now].mp.erase(s);//只删除边
update(now,(-1)*node[indexOfS].sz);//每个节点减少删除节点的size
//将操作放入undo的vector中
point p;
p.name="RM",p.now=now,p.next=indexOfS;
v.push_back(p);
cout<<"OK"<<endl;
}
else cout<<"ERR"<<endl;
}
void CD(string &s) //进入子目录s,储存操作为undo做准备,更新now
{
if(s=="..") //返回上级目录
{
if(node[now].fa==-1) //根目录
cout<<"ERR"<<endl;
else
{
//将操作放到undo的vector中
point p;
p.name="CD",p.now=now,p.next=node[now].fa;
v.push_back(p);
now=node[now].fa;//更新now
cout<<"OK"<<endl;
}
}
else //进入子目录s
{
if(node[now].mp.count(s)==1) //存在s才进入
{
//将操作放到undo的vector中
point p;
p.name="CD",p.now=now,p.next=node[now].mp[s];
v.push_back(p);
now=node[now].mp[s];//更新now
cout<<"OK"<<endl;
}
else cout<<"ERR"<<endl;
}
}
void SZ() //输出当前目录的大小
{
cout<<node[now].sz<<endl;
}
void LS() //输出当前目录的直接子目录名
{
if(node[now].mp.size()==0) //没有子目录
cout<<"EMPTY"<<endl;
else if(node[now].mp.size()>=1&&node[now].mp.size()<=10) //全部输出
{
for(map<string,int>::iterator it=node[now].mp.begin(); it!=node[now].mp.end(); it++)
cout<<it->first<<endl;
}
else //输出前五个和后五个
{
//前五个
map<string,int>::iterator it=node[now].mp.begin();
for(int i=1; i<=5; i++)
{
cout<<it->first<<endl;
it++;
}
cout<<"..."<<endl;
//后五个
it=node[now].mp.end();
for(int i=1; i<=5; i++)
it--;
for(int i=1; i<=5; i++)
{
cout<<it->first<<endl;
it++;
}
}
}
void alltrack(int id,vector<string> &pre) //前序遍历id子树(小于10个时)
{
pre.push_back(node[id].name);
for(map<string,int>::iterator it=node[id].mp.begin(); it!=node[id].mp.end(); it++)
alltrack(it->second,pre);
}
void pretrack(int id,vector<string> &pre,int &num) //前序遍历id子树,求出前五个
{
pre.push_back(node[id].name);
num--;
if(num==0) return;
for(map<string,int>::iterator it=node[id].mp.begin(); it!=node[id].mp.end(); it++)
{
pretrack(it->second,pre,num);
if(num==0) break;
}
}
void bcktrack(int id,vector<string> &bck,int &num) //右左根遍历id子树,求出后五个
{
map<string,int>::iterator it=node[id].mp.end();
int n=node[id].mp.size();
for(int i=0;i<n;i++)
{
it--;
bcktrack(it->second,bck,num);
if(num==0) return;
}
bck.push_back(node[id].name);
num--;
}
void pushdown(int id) //遍历id子树
{
node[id].pre.clear();
node[id].bck.clear();
if(node[id].sz<=10)
alltrack(id,node[id].pre);
else
{
int num=5;
pretrack(id,node[id].pre,num);
num=5;
bcktrack(id,node[id].bck,num);
}
node[id].tag=1;//标记为已改变,即最新
}
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=4;i>=0;i--)
cout<<node[now].bck[i]<<endl;
}
}
void UNDO() //撤销最近一个成功执行的MKDIR或RM或CD
{
if(v.size()==0) //没有操作
cout<<"ERR"<<endl;
else
{
point p=v[v.size()-1];//队尾弹出
v.pop_back();
cout<<"OK"<<endl;
if(p.name=="MKDIR") //要删除
{
update(p.now,(-1)*node[p.next].sz);
node[p.now].mp.erase(node[p.next].name);
}
else if(p.name=="RM") //要添加
{
update(p.now,node[p.next].sz);
node[p.now].mp[node[p.next].name]=p.next;
}
else //要返回
now=p.now;
}
}
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
for(int t1=0; t1<t; t1++)
{
if(t1!=0) //测试数据之间输出空行
cout<<endl;
int q;
cin>>q;
//初始化
//根节点为node[0],其父亲为-1
now=0,idx=1;
node[0].name="root",node[0].fa=-1,node[0].sz=1,node[0].tag=0;
node[0].pre.clear(),node[0].bck.clear(),node[0].mp.clear();
v.clear();
for(int q1=0; q1<q; q1++)
{
string op;
cin>>op;
if(op=="MKDIR")
{
string s;
cin>>s;
MKDIR(s);
}
else if(op=="RM")
{
string s;
cin>>s;
RM(s);
}
else if(op=="CD")
{
string s;
cin>>s;
CD(s);
}
else if(op=="SZ")
SZ();
else if(op=="LS")
LS();
else if(op=="TREE")
TREE();
else if(op=="UNDO")
UNDO();
}
}
}
B - 东东学打牌
问题描述
最近,东东沉迷于打牌。所以他找到 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 张牌不同,其值不同。下面依次列举了这手牌的形成规则:
1.大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。
2.对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。
3.两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。
4.三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。
5.三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。
6.炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。
7.顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。
8.龙顺:5 张牌分别为 10、J、Q、K、A。
作为一个称职的魔法师,东东得知了全场人手里 5 张牌的情况。他现在要输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。
不料,此时一束宇宙射线扫过,为了躲避宇宙射线,东东慌乱中清空了他脑中的 Cache。请你告诉东东,全场人的排名
输入
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。
输出
对于每组测试数据,输出 n 行,即这次全场人的排名。
样例输入
3
DongDong AAA109
ZJM 678910
Hrz 678910
样例输出
Hrz
ZJM
DongDong
解题思路
- 本题难度不大,只是较为复杂
- 注意从8到1条件是逐渐“变小“的,比如考虑是否为2时不需要考虑是不是3,所以从8到1依次判断即可。
- 结构体存储名字、扑克牌、分数即各种类别的牌对应的比较指标。
- 给所有扑克牌赋类别,比较即可。
完整代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct People
{
char name[11];//名字
int s[5];//扑克牌
int mark;//分数
int shunzi;//存最大值
int boom[2];//boom[0]为炸弹的牌,boom[1]为另一个
int sandaier[2];//0为'3',1为'2'
int sange[2];//0为'3',1为'2'的和
int liangdui[3];//0为大对,1为小对,2为单独
int duizi[2];//0为对子,1为剩余和
int dapai;//5个总和
void init()
{
memset(name,0,sizeof(name));
memset(s,0,sizeof(s));
mark=0;
}
};
People p[100010];
bool xiaoyu(People a,People b)//根据种类比较 ,return a<b
{
if(a.mark!=b.mark)
return a.mark<b.mark;
//相等
switch(a.mark)
{
case 1:
if(a.dapai!=b.dapai)
return a.dapai<b.dapai;
break;
case 2:
if(a.duizi[0]!=b.duizi[0])
return a.duizi[0]<b.duizi[0];
if(a.duizi[1]!=b.duizi[1])
return a.duizi[1]<b.duizi[1];
break;
case 3:
if(a.liangdui[0]!=b.liangdui[0])
return a.liangdui[0]<b.liangdui[0];
if(a.liangdui[1]!=b.liangdui[1])
return a.liangdui[1]<b.liangdui[1];
if(a.liangdui[2]!=b.liangdui[2])
return a.liangdui[2]<b.liangdui[2];
break;
case 4:
if(a.sange[0]!=b.sange[0])
return a.sange[0]<b.sange[0];
if(a.sange[1]!=b.sange[1])
return a.sange[1]<b.sange[1];
break;
case 5:
if(a.sandaier[0]!=b.sandaier[0])
return a.sandaier[0]<b.sandaier[0];
if(a.sandaier[1]!=b.sandaier[1])
return a.sandaier[1]<b.sandaier[1];
break;
case 6:
if(a.boom[0]!=b.boom[0])
return a.boom[0]<b.boom[0];
if(a.boom[1]!=b.boom[1])
return a.boom[1]<b.boom[1];
break;
case 7:
if(a.shunzi!=b.shunzi)
return a.shunzi<b.shunzi;
break;
}
int l1=strlen(a.name),l2=strlen(b.name);
for(int ii=0;ii<min(l1,l2);ii++)
{
if(a.name[ii]==b.name[ii]) continue;
if(a.name[ii]>b.name[ii]) return true;
if(a.name[ii]<b.name[ii]) return false;
}
//都相等,比长度,长度小的获胜
if(l1>l2) return true;
return false;
}
void judgetype(int i)
{
sort(p[i].s,p[i].s+5);
// for(int i=0;i<5;i++)
// cout<<p[i].s[i]<<" ";cout<<endl;
if(p[i].s[0]==1 && p[i].s[1]==10 && p[i].s[2]==11&&p[i].s[3]==12&&p[i].s[4]==13)
{p[i].mark=8;
}
else if(p[i].s[0]==p[i].s[1] && p[i].s[1]==p[i].s[2] && p[i].s[2]==p[i].s[3] && p[i].s[3]==p[i].s[4])
{
p[i].mark=1;p[i].dapai=p[i].s[0]+p[i].s[1]+p[i].s[2]+p[i].s[3]+p[i].s[4];}
else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]!=p[i].s[4])
{p[i].mark=6;
p[i].boom[0]=p[i].s[0];
p[i].boom[1]=p[i].s[4];}
else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[4]&&p[i].s[3]!=p[i].s[4])
{p[i].mark=6;
p[i].boom[0]=p[i].s[0];
p[i].boom[1]=p[i].s[3]; }
else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[2]!=p[i].s[4])
{p[i].mark=6;
p[i].boom[0]=p[i].s[0];
p[i].boom[1]=p[i].s[2]; }
else if(p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[0]!=p[i].s[4])
{p[i].mark=6;
p[i].boom[0]=p[i].s[1];
p[i].boom[1]=p[i].s[0]; }
else if(p[i].s[0]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[1]!=p[i].s[4])
{p[i].mark=6;
p[i].boom[0]=p[i].s[0];
p[i].boom[1]=p[i].s[1]; }
else if(p[i].s[1]==p[i].s[0]+1&&p[i].s[2]==p[i].s[1]+1&&p[i].s[3]==p[i].s[2]+1&&p[i].s[4]==p[i].s[3]+1)
{p[i].mark=7;p[i].shunzi=p[i].s[4]; }
else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2] && p[i].s[3]==p[i].s[4]&&p[i].s[0]!=p[i].s[3])
{
p[i].mark=5;
p[i].sandaier[0]=p[i].s[0];
p[i].sandaier[1]=p[i].s[3];
}
else if(p[i].s[0]==p[i].s[1] && p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4] && p[i].s[0]!=p[i].s[3])
{
p[i].mark=5;
p[i].sandaier[0]=p[i].s[2];
p[i].sandaier[1]=p[i].s[0];
}
else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2])
{
p[i].mark=4;
p[i].sange[0]=p[i].s[0];
p[i].sange[1]=p[i].s[3]+p[i].s[4];
}
else if(p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3])
{
p[i].mark=4;
p[i].sange[0]=p[i].s[1];
p[i].sange[1]=p[i].s[0]+p[i].s[4];
}
else if(p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4])
{
p[i].mark=4;
p[i].sange[0]=p[i].s[2];
p[i].sange[1]=p[i].s[0]+p[i].s[1];
}
else if(p[i].s[0]==p[i].s[1]&&p[i].s[2]==p[i].s[3])
{
p[i].mark=3;
p[i].liangdui[0]=p[i].s[3];
p[i].liangdui[1]=p[i].s[1];
p[i].liangdui[2]=p[i].s[4];
}
else if(p[i].s[1]==p[i].s[2]&&p[i].s[3]==p[i].s[4])
{
p[i].mark=3;
p[i].liangdui[0]=p[i].s[3];
p[i].liangdui[1]=p[i].s[1];
p[i].liangdui[2]=p[i].s[0];
}
else if(p[i].s[0]==p[i].s[1]&&p[i].s[3]==p[i].s[4])
{
p[i].mark=3;
p[i].liangdui[0]=p[i].s[3];
p[i].liangdui[1]=p[i].s[1];
p[i].liangdui[2]=p[i].s[2];
}
else if(p[i].s[0]==p[i].s[1])
{
p[i].mark=2;
p[i].duizi[0]=p[i].s[0];
p[i].duizi[1]=p[i].s[2]+p[i].s[3]+p[i].s[4];
}
else if(p[i].s[1]==p[i].s[2])
{
p[i].mark=2;
p[i].duizi[0]=p[i].s[1];
p[i].duizi[1]=p[i].s[0]+p[i].s[3]+p[i].s[4];
}
else if(p[i].s[2]==p[i].s[3])
{
p[i].mark=2;
p[i].duizi[0]=p[i].s[2];
p[i].duizi[1]=p[i].s[0]+p[i].s[1]+p[i].s[4];
}
else if(p[i].s[3]==p[i].s[4])
{
p[i].mark=2;
p[i].duizi[0]=p[i].s[3];
p[i].duizi[1]=p[i].s[0]+p[i].s[1]+p[i].s[2];
}
else
{
p[i].mark=1;
p[i].dapai=p[i].s[0]+p[i].s[1]+p[i].s[2]+p[i].s[3]+p[i].s[4];
}
}
int main()
{
int n;
char pai[11];
int cnt=0;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{p[i].init();
memset(pai,0,sizeof(pai));
cin>>p[i].name>>pai;
int length=strlen(pai);
for(int l=0;l<length;l++)
{if(pai[l]=='A')
p[i].s[cnt]=1;
else if(pai[l]=='J')
p[i].s[cnt]=11;
else if(pai[l]=='Q')
p[i].s[cnt]=12;
else if(pai[l]=='K')
p[i].s[cnt]=13;
else if(pai[l]=='1')
{p[i].s[cnt]=10;
l++;}
else
p[i].s[cnt]=int(pai[l]-'0');
//cout<<p[i].s[cnt]<<endl;
cnt++;
}
cnt=0;
}
for(int i=0;i<n;i++)
judgetype(i);
//cout<<"mark"<<p[i].mark<<endl;
sort(p,p+n,xiaoyu);
for(int i=n-1;i>=0;i--)
{ cout<<p[i].name<<endl;}
// for(int m=0;m<5;m++)
// cout<<p[i].s[m]<<" ";
// cout<<endl;}
}}
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
解题思路
- 对所有长椅根据人数排序,获得最大值,记为m
- 设来了y人,则最大人数就是m+y;
- 最小值
- 因为当前最多人的长椅不会变少,所以最小值大于等于m;用y把每个长椅的人补到m,每次y减去用的人数,即使y变负;
- y为负,则说明不够补到m,最大值为m
- y为正,则说明补到m还有剩余,则把剩下的y-m个人尽可能的平均分即可。
完整代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[1000];
int main()
{
int x,y;
cin>>x>>y;
int m=y;
for(int i=0;i<x;i++)
cin>>a[i];
sort(a,a+x);
for(int i=0;i<x-1;i++)
{y=y-(a[x-1]-a[i]);}//把他们都补到当前最大值
if(y<0)//最大值就是原来的最大值
cout<<a[x-1]<<" ";
else//平均分
{
int n=y/x;
int left=y%x;
if(left!=0)
left=1;
cout<<a[x-1]+n+left<<" ";
}
cout<<a[x-1]+m<<endl;
}