答题序号 | 题目名称 | 分数 | 当前状态 | 得分 | 通过率 |
1. | 顺丰小哥分拣快递 | 10 | 通过 | 10 | 68% |
2. | 顺丰管理处罚系统 | 20 | 未通过 | 0 | 14% |
3. | 顺丰小哥送快递 | 30 | 未通过 | 0 | 9% |
4. | 顺丰主管调度 | 40 | 未通过 | 0 | 16% |
明年再战吧,AK的大佬都是学了四五年的,半决赛前50名:进决赛+ 校招pass卡。(看了一下排名,总赛区前200名进决赛,一小时内50分就进了,)
顺丰小哥分拣快递
顺丰小哥是顺丰的仓管员,他每天都需要对快递进行分拣。
我们用不同的字符表示快递的类型,共有小写字母、大写字母、数字三种类型。顺丰小哥需要把相同类型的快递分拣到一起。请你编写一个程序完成这个操作。
输入描述:
一个字符串,代表顺丰小哥拿到的所有快递。
保证每种类型的快递至少有一个。
字符串仅由大小写字母和数字组成,长度不超过200000。
输出描述:
一共输出三行字符串,代表分拣后的结果。不同字符串需要按照顺丰小哥拿到快递的顺序进行输出。
第一行输出小写字母类型的快递。
第二行输出大写字母类型的快递。
第三行输出数字类型的快递。
示例1
输入:
aBc3g4G
输出:
acg
BG
34
第一题签到题五分钟不用就做完了,but也只做了这一题。
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<char> v1;
vector<char> v2;
vector<char> v3;
string s;
cin >> s;
for (int i = 0; s[i]; ++i) {
if (s[i] >= 'a' && s[i] <= 'z') v1.emplace_back(s[i]);
else if (s[i] >= 'A' && s[i] <= 'Z') v2.emplace_back(s[i]);
else if (s[i] >= '0' && s[i] <= '9') v3.emplace_back(s[i]);
}
for (int i = 0; i < v1.size(); ++i)
cout << v1[i];
puts("");
for (int i = 0; i < v2.size(); ++i)
cout << v2[i];
puts("");
for (int i = 0; i < v3.size(); ++i)
cout << v3[i];
puts("");
return 0;
}
顺丰管理处罚系统
顺丰里面有一个处罚管理系统,为了管理处罚系统,请你帮忙实现如下函数:
List<HistoryResult> query(int pageNo, int pageSize) :查询处罚记录,记录按照id升序排序
List<HistoryResult> getByUserId(int userId) :查询某个用户的处罚记录,记录按照id升序排序
int punish(String operatorUserName, int userId, int punishStatus) : 处罚操作, 如果用户已经有被处罚了,新的处罚必须高于当前处罚等级才能生效,operatorUserName为执行处罚的人,userId为被处罚用户的编号
int relieve(String operatorUserName, int userId) : 解除当前处罚,operatorUserName为解除处罚的人,userId为被解除处罚用户的编号。若当前用户无处罚记录则该操作无效。解除处罚的status设置为0
只有有效的处罚或解除处罚操作,才会被记录id。这两种操作的返回值为该操作的id,从1开始自增。若操作为无效操作,返回-1
输入描述:
第一行输入一个N(2<N<=200000),代表操作个数
接下来的每2行代表1个操作,
每2行的第1行输入一个操作的英文名字,代表对应的操作
每2行的第2行输入操作对应的参数
输出描述:
对应每个查询操作,记录一个结果,最后统一输出所有处罚操作和解除处罚操作的返回值,你只需要完成函数即可,输出无需理会
示例1
输入:
7
punish
bob 5 3
punish
bob 5 1
relieve
alice 3
relieve
alice 5
query
1 20
query
2 20
getByUserId
5
输出:
1_5_bob_3
2_5_alice_0
1_5_bob_3
2_5_alice_0
1
-1
-1
2
说明:
前两行为query 1 20的输出,query 2 20没有输出。第3行和第4行为getByUserId 5的输出。最后4行依次为4次处罚/解除处罚操作的返回值。
示例2
输入:
4
punish
bob 5 1
punish
bob 5 3
relieve
alice 5
punish
bob 5 3
输出:
1
2
3
4
我是第一次碰到这种题,就是C++的自己写类什么什么的。由于我的C++学的是山寨版的,就是C+cin,cout+STL,所以这题涉及到知识盲区,等我暑假学了完整版的C++后,再肥来····
#include <bits/stdc++.h>
using namespace std;
class HistoryResult
{
public:
HistoryResult(int id, int userId, string operatorUserName, int status)
{
this->id = id;
this->userId = userId;
this->operatorUserName = operatorUserName;
this->status = status;
}
int getId() const
{
return id;
}
int getUserId() const
{
return userId;
}
string getOperatorUserName() const
{
return operatorUserName;
}
int getStatus() const
{
return status;
}
private:
int id;
int userId;
string operatorUserName;
int status;
};
class Main
{
public:
/**
* 查询处罚记录,记录按照id升序排序
*
* @param pageNo 第几页
* @param pageSize 页数大小
* @return 查询结果
*/
vector<HistoryResult> query(int pageNo, int pageSize)
{
}
/**
* 查询某个用户的处罚记录,记录按照id升序排序
*
* @param userId 用户
* @return 处罚记录
*/
vector<HistoryResult> getByUserId(int userId)
{
}
/**
* 处罚操作, 如果用户已经有被处罚了,新的处罚不能低于当前处罚等级才能生效
*
* @param operatorUserName 操作者的名字
* @param userId 处罚的用户
* @param punishStatus 处罚类型
* @return 返回处罚的记录id, 处罚不成功返回-1
*/
int punish(string operatorUserName, int userId, int punishStatus)
{
}
/**
* 解除当前处罚
*
* @param operatorUserName 操作者的名字
* @param userId 解除处罚的用户
* @return 如果当前用户正在被处罚中,解除当前处罚,返回处罚记录id,如果用户没有被处罚,返回-1表示解除处罚非法
*/
int relieve(string operatorUserName, int userId)
{
}
};
int main()
{
Main main;
int opNum;
cin >> opNum;
cin.ignore();
vector<HistoryResult> printHistory;
vector<int> printOperators;
for (int i = 0; i < opNum; ++i)
{
string op;
getline(cin, op);
string data;
getline(cin, data);
if (op == "punish")
{
std::istringstream iss(data);
std::string operatorUserName;
int userId;
int punishStatus;
iss >> operatorUserName >> userId >> punishStatus;
printOperators.push_back(main.punish(operatorUserName, userId, punishStatus));
}
else if (op == "relieve")
{
std::istringstream iss(data);
string operatorUserName;
int userId;
iss >> operatorUserName >> userId;
printOperators.push_back(main.relieve(operatorUserName, userId));
}
else if (op == "getByUserId")
{
std::istringstream iss(data);
int userId;
iss >> userId;
vector<HistoryResult> results = main.getByUserId(userId);
if (!results.empty())
{
printHistory.insert(printHistory.end(), results.begin(), results.end());
}
}
else if (op == "query")
{
std::istringstream iss(data);
int pageNo, pageSize;
iss >> pageNo >> pageSize;
vector<HistoryResult> results = main.query(pageNo, pageSize);
if (!results.empty())
{
printHistory.insert(printHistory.end(), results.begin(), results.end());
}
}
else
{
cout << "错误的输入" << endl;
}
}
for (const HistoryResult &result : printHistory)
{
cout << result.getId() << "_" << result.getUserId() << "_"
<< result.getOperatorUserName() << "_" << result.getStatus() << endl;
}
for (int operatorResult : printOperators)
{
cout << operatorResult << endl;
}
return 0;
}
顺丰小哥送快递
地图上有n个城市,m条道路。每个道路连接着两个城市。顺丰小哥需要将快递从1号城市运到号城市,
另外,顺丰小哥有一个魔法,他可以花费时间从一个城市传送到任意另一个城市。为了避免暴露自己会魔法的事实,他不会在起点和终点使用魔法(也不会作为魔法的目的地),且魔法最多只能使用一次。
顺丰小哥想知道,自己完成送快递至少需要多少时间?
输入描述
第一行输出三个正整数n,m,x,代表城市数量、道路数量以及顺丰小哥使用魔法需要耗费的时间。
接下来的m行,每行输出三个正整数u,v,w,代表u号城市和v号城市有一条双向道路连接,且顺丰小哥使用该道路需要花费的时间为w。
1 <= n, m <= 10⁵
1 <= u, v <= n
1 <= x, w <= 10⁹
输出描述:
如果顺丰小哥无法完成运货,则输出-1。
否则输出最小需要花费的时间。
示例1
输入:
4 2 5
1 2 1
3 4 1
输出:
7
说明:
顺丰小哥先花费1的时间从1号城市走到2号城市,然后使用魔法传送到3号城市,之后再花费1的时间从3号城市走到4号城市。
示例2
输入:
4 3 5
1 2 1
3 4 1
2 3 2
输出:
4
说明:
顺丰小哥不需要使用魔法,花费4的时间即可。路线为1->2->3->4。
怎么说呢这题,应该是我感觉就差一步之遥就做出来了,就差一点点,然后看了一位大佬的思路就豁然开朗,和他想的是差不多:
1.如果1或者n没有邻接点,返回-1
2.使用魔法:取1邻接点最近点距离x1,n邻接点最近点距离x2,然后代价就是x1+x2+x魔法
3.不使用魔法:dijstra查1到n的最短距离,不通则为max_int
返回使用魔法和不使用魔法中距离更短的那个
这个分情况分的很好,第一种情况我想到了,主要是第二和第三种情况当时迷迷糊糊没有明确拆开来😟
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
int n, m, u, v;
ll x, w, l1, l2;
ll dist[N];
bool vis[N];
struct edge {
int to;
ll w;
edge(int a, ll b) { to = a, w = b; }
};
vector<edge> g[N];
struct node {
int id;
ll dis;
node(int a, ll b) { id = a, dis = b; }
bool operator < (const node& u) const { return dis > u.dis; }
};
int main() {
cin >> n >> m >> x;
for (int i = 1; i <= n; ++i) dist[i] = 10000000000;
while (m--) {
cin >> u >> v >> w;
g[u].emplace_back(edge(v, w));
g[v].emplace_back(edge(u, w));
}
//1.如果1或者n没有邻接点,返回-
if (g[1].empty() || g[n].empty()) {
cout << -1;
return 0;
}
//2.使用魔法:取1邻接点最近点距离x1,n邻接点最近点距离x2,然后代价就是x1+x2+x魔法
ll x1, x2;
x1 = x2 = 0x3f3f3f3f;
for (int i = 0; i < g[1].size(); ++i) {
x1 = min(x1, g[1][i].w);
}
for (int i = 0; i < g[n].size(); ++i) {
x2 = min(x2, g[n][i].w);
}
l1 = x1 + x2 + x;
//3.不使用魔法:dijstra查1到n的最短距离,不通则为0x3f3f3f3f
priority_queue<node> q;
dist[1] = 0;
q.emplace(node(1, dist[1]));
while (q.size()) {
node u = q.top(); q.pop();
if (vis[u.id]) continue;
vis[u.id] = 1;
for (int i = 0; i < g[u.id].size(); ++i) {
edge e = g[u.id][i];
if (vis[e.to]) continue;
if (dist[e.to] > u.dis + e.w) {
dist[e.to] = u.dis + e.w;
q.emplace(node(e.to, dist[e.to]));
}
}
}
l2 = dist[n];
cout << min(l1, l2);
return 0;
}
分析错点:第一次错误是因为我没有用邻接表存,他的最大数据是要开g[n][n](n = 10⁵)会爆掉,后面改了,用邻接表存就直接百分之90多的测试点过了。第二次错误是因为我把int改成long long因为他的长度最大是10⁹多来几个边就会爆int所以换了long long。第三次又将dist数组的初值赋为0x3f3f3f3f改成1000000005就比10⁹多个5,结果只过了百分之80多的测试点。后面意识到自己傻蛋了应该更大点然后就赋值10的十次方就AC了。
太后悔了这题,会错的,当时比赛没做出,就是想不到,题目刷太少!
顺丰主管调度
顺丰主管将对他手下的兼职快递员们进行任务安排。
已知快递分为两种类型,第一种类型为同城快送,第二种类型为跨城运输。顺丰主管手下有n个兼职快递员,每个快递员的工资分别为ai,运送快递的顾客满意值为bi。快递员有两种类型:类型A只能送同城快运,类型B则可以送任意快递。
顺丰主管共有x个同城快送任务,y个跨城运输任务。他需要把这些快递派发给他手下的快递员,每个人最多只能接一个任务。顺丰主管想知道,在支付总工资尽可能小的情况下,最终的顾客满意值之和最大是多少?
注:任务必须全部接完。每个快递员只能接一个任务。
输入描述:
第一行输入四个正整数n, x, y,分别代表快递员数量和两种类型任务的数量。
接下来的n行,每行输入一个字符type和两个正整数ai, bi用来描述每个快递员的类型以及工资和顾客满意值。
1 <= n, x, y <= 10⁵
1 <= ai, bi <= 10⁹
保证type字符是'A'或者'B'。
输出描述:
如果无法接完全部任务,则输出-1。
否则一个整数,代表最终最大的顾客满意值。
示例1
输入:
3 1 1
A 2 5
B 2 3
A 3 7
输出:
8
说明:
选择第一个快递员做第一个类型的任务,第二个做第二个类型的任务,总工资为4,满意值之和为8。
请注意,如果选择第二个和第三个快递员,虽然能达成更高的满意度,但需要支付5的总工资,不符合要求。
示例2
输入:
2 1 1
A 2 300
A 9 1000
输出:
-1
说明:
两个快递员都是A类型,只能送同城快送,无法完成跨城运输任务。因此输出-1。
早知道先做第四题的 早知道先做第四题的 早知道先做第四题的 以为分数高 死磕第三题去了~~>_<~~
然后第一次提交的时候以为没有用long long所以还是错了一下 太不细心了 不然可以进决赛的😭
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, x, y;
char c;
ll a, b, ans;
struct node {
ll a, b;
char c;
node(ll x, ll y, char z) { a = x, b = y, c = z; }
};
struct Rule {
bool operator()(const node& n1, const node& n2)const {
if (n1.a == n2.a) {
if (n1.b == n2.b) {
return n1.c < n2.c;
}
else return n1.b > n2.b;
}
else return n1.a < n2.a;
}
};
multiset<node, Rule> st;
int main() {
cin >> n >> x >> y;
for (int i = 0; i < n; ++i) {
cin >> c >> a >> b;
st.insert(node(a, b, c));
}
for (auto e:st){
if (e.c == 'A') {
if (x) {
x--;
ans += e.b;
}
}
else {
if (y) {
y--;
ans += e.b;
}
else if (x) {
x--;
ans += e.b;
}
}
}
if (x != 0 || y != 0) {
cout << -1;
}
else cout << ans;
return 0;
}