本文共 55037 字,大约阅读时间需要 183 分钟。
sort()
/ stable_sort()
进行排序,详细用法见如果是多关键字排序,例如:
bool cmp(Student a, Student b) { if(a.score != b.score) return a.score > b.score; else return strcmp(a.name, b.name) < 0;}
stu[0].r = 1;for(int i = 1; i < n; i++) { if(stu[i].score == stu[i - 1].score) { stu[i].r = stu[i - 1].r; } else { stu[i].r = i + 1; }}
int
型变量r
初值为1, 然后遍历所有个体: 如果当前个体不是第一个个体且当前个体的分数不等于上一个个体的分数, 那么令r
等于数组下标加1
, 这时r
就是当前个体的排名, 直接输出即可int r = 1;for(int i = 0; i < n; i++) { if(i > 0 && stu[i].score != stu[i - 1].score) { r = i + 1; } //输出当前个体信息, 或者令stu[i] .r = r 也行}
#include <cstdio>#include <map>#include <vector>#include <string>#include <iterator>#include <algorithm>using namespace std;struct Stu { char id[7]; int grade[4]; // A, C, M, E char rank_mark; int rank = 0;};map<string, pair<int, char>> rank_map;vector<Stu> stu;int n, m;void sort_func(int idx){ int rank = 1; map<int, char> symbol_map = { { 0, 'A'}, { 1, 'C'}, { 2, 'M'}, { 3, 'E'} }; sort(begin(stu), end(stu), [idx](const Stu& lhs, const Stu& rhs) -> bool { return lhs.grade[idx] > rhs.grade[idx]; }); for (int i = 0; i != n; ++i) { if (i != 0 && stu[i].grade[idx] != stu[i - 1].grade[idx]) { rank = i + 1; } pair<int, char>& rres = rank_map[string(stu[i].id)]; if (rank < rres.first || rres.first == 0) { rres.first = rank; rres.second = symbol_map[idx]; } }}int main(int argc, const char* argv[]) { scanf("%d %d", &n, &m); for(size_t i = 0; i != n; ++i) { Stu tmp; scanf("%s %d %d %d", tmp.id, &tmp.grade[1], &tmp.grade[2], &tmp.grade[3]); tmp.grade[0] = tmp.grade[1] + tmp.grade[2] + tmp.grade[3]; rank_map.insert({ string(tmp.id), { 0, 'A'} }); stu.push_back(std::move(tmp)); } for (size_t i = 0; i != 4; ++i) { sort_func(i); } while (m--) { char id[7]; scanf("%s", id); if (rank_map.find(string(id)) == rank_map.end()) { printf("N/A\n"); } else { pair<int, char>& rres = rank_map[string(id)]; printf("%d %c\n", rres.first, rres.second); } } return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <string>#include <map>using namespace std;struct Rec { int time[3]; // day, hour, min int flag; // 0: on-line 1: off-line 2: void};vector<int> toll(24);long long toll_a_day = 0; // 打一天电话的费用long long min_a_day = 24 * 60;int N, Month;map<string, vector<Rec>> Data;pair<long long, long long> calc_cost_and_time(const Rec& beg, const Rec& end){ if (beg.time[0] != end.time[0]) { Rec tmp1 = beg; tmp1.time[1] = 23; tmp1.time[2] = 60; Rec tmp2 = end; tmp2.time[1] = 0; tmp2.time[2] = 0; auto res1 = calc_cost_and_time(beg, tmp1); auto res2 = calc_cost_and_time(tmp2, end); return { res1.first + res2.first + toll_a_day * (end.time[0] - beg.time[0] - 1), res1.second + res2.second + min_a_day * (end.time[0] - beg.time[0] - 1) }; } else { if (beg.time[1] == end.time[1]) { return { toll[beg.time[1]] * (end.time[2] - beg.time[2]), end.time[2] - beg.time[2] }; } else { long long cost = 0, time = 0; for (int hour = beg.time[1] + 1; hour < end.time[1]; ++hour) { cost += toll[hour] * 60; time += 60; } return { cost + toll[beg.time[1]] * (60 - beg.time[2]) + toll[end.time[1]] * end.time[2], time + (60 - beg.time[2]) + end.time[2] }; } }}int main(int argc, const char* argv[]) { for (int i = 0; i != 24; ++i) { scanf("%d", &toll[i]); toll_a_day += toll[i] * 60; } scanf("%d", &N); for (int i = 0; i != N; ++i) { Rec tmp; char name[21], state[9]; scanf("%s %d:%d:%d:%d %s", name, &Month, &tmp.time[0], &tmp.time[1], &tmp.time[2], state, 9); tmp.flag = (state[1] == 'n') ? 0 : 1; Data[name].push_back(std::move(tmp)); } for (auto& customer : Data) { const string& name = customer.first; vector<Rec>& rec = customer.second; double cost = 0; sort(rec.begin(), rec.end(), [](const Rec& lhs, const Rec& rhs) -> bool { return (lhs.time[0] * 1e4 + lhs.time[1] * 1e2 + lhs.time[2]) < (rhs.time[0] * 1e4 + rhs.time[1] * 1e2 + rhs.time[2]); }); for (size_t i = 0; i != rec.size(); ++i) { if (rec[i].flag == 0 && i + 1 != rec.size() && rec[i + 1].flag == 1) { // matched records if (cost == 0) { printf("%s %02d\n", name.c_str(), Month); } auto cost_and_time = calc_cost_and_time(rec[i], rec[i + 1]); printf("%02d:%02d:%02d %02d:%02d:%02d %lld $%.2f\n", rec[i].time[0], rec[i].time[1], rec[i].time[2], rec[i + 1].time[0], rec[i + 1].time[1], rec[i + 1].time[2], cost_and_time.second, cost_and_time.first / 100.0); cost += cost_and_time.first / 100.0; rec[i + 1].flag = 2; } } if (cost != 0) { printf("Total amount: $%.2f\n", cost); } } return 0;}
merge
来归并不同考场的考生了。其实还是应该把所有考生都存在一个容器里,再进行一次总的排序,这样更简单#include <cstdio>#include <vector>#include <algorithm>#include <cstring>#include <iterator>using namespace std;struct Testee { char id[14]; char score; int loc_rank; char loc_num;};int N;vector<Testee> all1, all2;bool cmp(const Testee& lhs, const Testee& rhs){ if (lhs.score == rhs.score) { return strcmp(lhs.id, rhs.id) < 0; } else { return lhs.score > rhs.score; }}int main(int argc, const char* argv[]) { scanf("%d", &N); for (int i = 1; i <= N; ++i) { int K; scanf("%d", &K); vector<Testee> loc; while (K--) { Testee testee; scanf("%s %d", testee.id, &testee.score); testee.loc_num = i; loc.push_back(std::move(testee)); } sort(loc.begin(), loc.end(), cmp); int rk = 1; for (size_t j = 0; j != loc.size(); ++j) { if (j != 0 && loc[j].score != loc[j - 1].score) { rk = j + 1; } loc[j].loc_rank = rk; } vector<Testee>& all_res = (all1.size() < all2.size()) ? all1 : all2; vector<Testee>& all_merge = (all1.size() > all2.size()) ? all1 : all2; all_res = vector<Testee>(); if (all_merge.size() == 0) { all_res = std::move(loc); } else { merge(loc.begin(), loc.end(), all_merge.begin(), all_merge.end(), back_inserter(all_res), cmp); } } vector<Testee>& all_res = (all1.size() > all2.size()) ? all1 : all2; printf("%d\n", all_res.size()); int rk = 1; for (size_t j = 0; j != all_res.size(); ++j) { if (j != 0 && all_res[j].score != all_res[j - 1].score) { rk = j + 1; } printf("%s %d %d %d\n", all_res[j].id, rk, all_res[j].loc_num, all_res[j].loc_rank); } return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <cstring>using namespace std;struct Man { char id[9]; int grade[2]; // virtual, talent};int N, L, H;vector<Man> sages, nobel, fool, small;bool cmp(const Man& lhs, const Man& rhs){ int sumL = lhs.grade[0] + lhs.grade[1]; int sumR = rhs.grade[0] + rhs.grade[1]; if (sumL == sumR) { if (lhs.grade[0] == rhs.grade[0]) { return strcmp(lhs.id, rhs.id) < 0; } else { return lhs.grade[0] > rhs.grade[0]; } } else { return sumL > sumR; }}int main(int argc, const char* argv[]) { scanf("%d %d %d", &N, &L, &H); for (int i = 0; i != N; ++i) { Man tmp; scanf("%s %d %d", tmp.id, &tmp.grade[0], &tmp.grade[1]); if (tmp.grade[0] >= L && tmp.grade[1] >= L) { if (tmp.grade[0] >= H && tmp.grade[1] >= H) { sages.push_back(std::move(tmp)); } else if (tmp.grade[0] >= H && tmp.grade[1] < H) { nobel.push_back(std::move(tmp)); } else if (tmp.grade[0] < H && tmp.grade[1] < H && tmp.grade[0] >= tmp.grade[1]) { fool.push_back(std::move(tmp)); } else { small.push_back(std::move(tmp)); } } } printf("%d\n", sages.size() + nobel.size() + fool.size() + small.size()); sort(sages.begin(), sages.end(), cmp); for (size_t i = 0; i != sages.size(); ++i) { printf("%s %d %d\n", sages[i].id, sages[i].grade[0], sages[i].grade[1]); } sort(nobel.begin(), nobel.end(), cmp); for (size_t i = 0; i != nobel.size(); ++i) { printf("%s %d %d\n", nobel[i].id, nobel[i].grade[0], nobel[i].grade[1]); } sort(fool.begin(), fool.end(), cmp); for (size_t i = 0; i != fool.size(); ++i) { printf("%s %d %d\n", fool[i].id, fool[i].grade[0], fool[i].grade[1]); } sort(small.begin(), small.end(), cmp); for (size_t i = 0; i != small.size(); ++i) { printf("%s %d %d\n", small[i].id, small[i].grade[0], small[i].grade[1]); } return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <map>using namespace std;struct Rec { int uid; // 1 ~ N int pid; // 1 ~ K int partial_score;};struct User { int rank; int uid; int total_score = 0; int s[5] = { -1, -1, -1, -1, -1}; int perfect_cnt = 0; bool flag = false;};int N, K, M; // user, problem, submissionint P[5]; // full markmap<int, User> Data;vector<User> Users;int main(int argc, const char* argv[]) { scanf("%d %d %d", &N, &K, &M); for(int i = 0; i != K; ++i) { scanf("%d", &P[i]); } for (int i = 0; i != M; ++i) { Rec tmp; scanf("%d %d %d", &tmp.uid, &tmp.pid, &tmp.partial_score); tmp.pid -= 1; User& user = Data[tmp.uid]; user.uid = tmp.uid; if (tmp.partial_score >= 0) { user.flag = true; } tmp.partial_score = (tmp.partial_score > 0) ? tmp.partial_score : 0; if (tmp.partial_score == P[tmp.pid] && P[tmp.pid] != Data[tmp.uid].s[tmp.pid]) { ++Data[tmp.uid].perfect_cnt; } if (Data[tmp.uid].s[tmp.pid] < tmp.partial_score) { Data[tmp.uid].s[tmp.pid] = tmp.partial_score; } } for (auto& user_pair : Data) { User& user = user_pair.second; if (user.flag) { for (int j = 0; j != K; ++j) { user.total_score += (user.s[j] > 0) ? user.s[j] : 0; } Users.push_back(user); } } sort(Users.begin(), Users.end(), [](const User& lhs, const User& rhs) -> bool { if (lhs.total_score == rhs.total_score) { if (lhs.perfect_cnt == rhs.perfect_cnt) { return lhs.uid < rhs.uid; } else { return lhs.perfect_cnt > rhs.perfect_cnt; } } else { return lhs.total_score > rhs.total_score; } }); int rank = 1; for (size_t i = 0; i != Users.size(); ++i) { if (i != 0 && Users[i].total_score != Users[i - 1].total_score) { rank = i + 1; } printf("%d %05d %d ", rank, Users[i].uid, Users[i].total_score); for (int j = 0; j != K; ++j) { if (Users[i].s[j] == -1) { printf("-"); } else { printf("%d", Users[i].s[j]); } if (j != K - 1) { printf(" "); } else { printf("\n"); } } } return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <unordered_set>using namespace std;struct Applicant { int id; int grade[2]; int final_grade; int choice[5]; size_t same_rank_cnt = 0; unordered_set<int> school_passed;};vector<Applicant> Applicants;int N, M, K; // applicant, school, choicesize_t Quota[100];vector<vector<int>> Res(100);int main(int argc, const char* argv[]) { scanf("%d %d %d", &N, &M, &K); for (int i = 0; i != M; ++i) { scanf("%lu", &Quota[i]); } for (int i = 0; i != N; ++i) { Applicant tmp; scanf("%d %d", &tmp.grade[0], &tmp.grade[1]); tmp.id = i; tmp.final_grade = tmp.grade[0] + tmp.grade[1]; for (int j = 0; j != K; ++j) { scanf("%d", &tmp.choice[j]); } Applicants.push_back(std::move(tmp)); } sort(Applicants.begin(), Applicants.end(), [](const Applicant& lhs, const Applicant& rhs) -> bool { if (lhs.final_grade != rhs.final_grade) { return lhs.final_grade > rhs.final_grade; } else if (lhs.grade[0] != rhs.grade[0]) { return lhs.grade[0] > rhs.grade[0]; } else { return lhs.id < rhs.id; } }); for (size_t i = 0; i != Applicants.size(); ++i) { size_t& same_rank_cnt = Applicants[i].same_rank_cnt; if (same_rank_cnt == 0) { same_rank_cnt = i + 1; for (; same_rank_cnt != Applicants.size() && Applicants[i].final_grade == Applicants[same_rank_cnt].final_grade && Applicants[i].grade[0] == Applicants[same_rank_cnt].grade[0]; ++same_rank_cnt) { } same_rank_cnt -= i; for (size_t j = 1; j != same_rank_cnt; ++j) { Applicants[i + j].same_rank_cnt = same_rank_cnt - j; } } for (int k = 0; k != K; ++k) { if (Applicants[i].school_passed.find(Applicants[i].choice[k]) != Applicants[i].school_passed.end()) { Res[Applicants[i].choice[k]].push_back(Applicants[i].id); break; } else if (Res[Applicants[i].choice[k]].size() < Quota[Applicants[i].choice[k]]) { Res[Applicants[i].choice[k]].push_back(Applicants[i].id); for (size_t j = 1; j != same_rank_cnt; ++j) { Applicants[i + j].school_passed.insert(Applicants[i].choice[k]); } break; } } } for (int i = 0; i != M; ++i) { sort(Res[i].begin(), Res[i].end()); for (size_t j = 0; j != Res[i].size(); ++j) { printf("%d", Res[i][j]); if (j + 1 != Res[i].size()) { printf(" "); } else { printf("\n"); } } if (Res[i].size() == 0u) { printf("\n"); } } return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <string>#include <unordered_map>#include <set>using namespace std;struct Rec { char plate_number[8]; int status; // 1: in -1:out int all_time; int time[3]; // h m s};unordered_map<string, vector<Rec>> recs;unordered_map<string, int> Time;vector<Rec> valid_recs;vector<int> query;int N, K; // record, queryint main(int argc, const char* argv[]) { scanf("%d %d", &N, &K); for (int i = 0; i != N; ++i) { Rec tmp; char status[4]; scanf("%s %d:%d:%d %s", tmp.plate_number, &tmp.time[0], &tmp.time[1], &tmp.time[2], status); tmp.all_time = tmp.time[0] * 10000 + tmp.time[1] * 100 + tmp.time[2]; tmp.status = (status[0] == 'i') ? 1 : -1; recs[tmp.plate_number].push_back(tmp); } for (auto& rec_pair : recs) { vector<Rec>& rec = rec_pair.second; sort(rec.begin(), rec.end(), [](const Rec& lhs, const Rec& rhs) -> bool { return lhs.all_time < rhs.all_time; }); for (size_t i = 0; i + 1 != rec.size(); ++i) { if (rec[i].status == 1 && rec[i + 1].status == -1) { auto interval_calc = [](const Rec& lhs, const Rec& rhs) -> int { int ds = lhs.time[2] - rhs.time[2]; int dm = lhs.time[1] - rhs.time[1]; int dh = lhs.time[0] - rhs.time[0]; if (ds < 0) { dm -= 1; ds += 60; } if (dm < 0) { dh -= 1; dm += 60; } return dh * 10000 + dm * 100 + ds; }; Time[rec_pair.first] += interval_calc(rec[i + 1], rec[i]); valid_recs.push_back(rec[i]); valid_recs.push_back(rec[i + 1]); } } } sort(valid_recs.begin(), valid_recs.end(), [](const Rec& lhs, const Rec& rhs) -> bool { return lhs.all_time < rhs.all_time; }); for (int i = 0; i != K; ++i) { int time[3]; scanf("%d:%d:%d", &time[0], &time[1], &time[2]); query.push_back(time[0] * 10000 + time[1] * 100 + time[2]); } size_t query_idx = 0; int car_cnt = 0; for (size_t i = 0; i != valid_recs.size() && query_idx != K; ++i) { if (valid_recs[i].all_time > query[query_idx]) { printf("%d\n", car_cnt); ++query_idx; } car_cnt += valid_recs[i].status; } for (; query_idx != K; ++query_idx) { printf("%d\n", car_cnt); } int max_time = 0; set<string> max_plate_numbers; for (const auto& time_pair : Time) { if (time_pair.second > max_time) { max_time = time_pair.second; max_plate_numbers = set<string>{ time_pair.first }; } else if (time_pair.second == max_time) { max_plate_numbers.insert(time_pair.first); } } for (const auto& plate_number : max_plate_numbers) { printf("%s ", plate_number.c_str()); } printf("%02d:%02d:%02d", max_time / 10000, (max_time % 10000) / 100, max_time % 100); return 0;}
#include <cstdio>#include <vector>#include <algorithm>#include <string>#include <unordered_map>#include <cstring>using namespace std;struct Rec { char plate_number[8]; int status; // 1: in -1:out int time; };unordered_map<string, int> Time;vector<Rec> recs;vector<Rec> valid_recs;int N, K; // record, queryint Max_time = 0;int main(int argc, const char* argv[]) { scanf("%d %d", &N, &K); for (int i = 0; i != N; ++i) { Rec tmp; int time[3]; char status[4]; scanf("%s %d:%d:%d %s", tmp.plate_number, &time[0], &time[1], &time[2], status); tmp.time = time[0] * 3600 + time[1] * 60 + time[2]; tmp.status = (status[0] == 'i') ? 1 : -1; recs.push_back(std::move(tmp)); } sort(recs.begin(), recs.end(), [](const Rec& lhs, const Rec& rhs) -> bool { int res = strcmp(lhs.plate_number, rhs.plate_number); if (res != 0) { return res < 0; } else { return lhs.time < rhs.time; } }); for (size_t i = 0; i + 1 != recs.size(); ++i) { if (recs[i].status == 1 && recs[i + 1].status == -1 && strcmp(recs[i].plate_number, recs[i + 1].plate_number) == 0) { Time[recs[i].plate_number] += recs[i + 1].time - recs[i].time; valid_recs.push_back(recs[i]); valid_recs.push_back(recs[i + 1]); Max_time = max(Max_time, Time[recs[i].plate_number]); } } sort(valid_recs.begin(), valid_recs.end(), [](const Rec& lhs, const Rec& rhs) -> bool { return lhs.time < rhs.time; }); size_t rec_idx = 0; int car_cnt = 0; for (int i = 0; i != K; ++i) { int tmp_time[3]; scanf("%d:%d:%d", &tmp_time[0], &tmp_time[1], &tmp_time[2]); int time = tmp_time[0] * 3600 + tmp_time[1] * 60 + tmp_time[2]; for (; rec_idx != valid_recs.size() && valid_recs[rec_idx].time <= time; ++rec_idx) { car_cnt += valid_recs[rec_idx].status; } printf("%d\n", car_cnt); } vector<string> max_plate_numbers; for (const auto& time_pair : Time) { if (time_pair.second == Max_time) { max_plate_numbers.push_back(time_pair.first); } } sort(max_plate_numbers.begin(), max_plate_numbers.end()); for (const auto& plate_number : max_plate_numbers) { printf("%s ", plate_number.c_str()); } printf("%02d:%02d:%02d", Max_time / 3600, (Max_time % 3600) / 60, Max_time % 60); return 0;}
unordered_map<string, vector<int>>
记录信息;但是本题最后一个测试点数据量很大,很容易超时;我下面的代码也是提交了好几次才勉勉强强通过的#include <iostream>#include <vector>#include <unordered_map>#include <string>#include <algorithm>using namespace std;int N, K;unordered_map<string, vector<int>> Data;int main(void){ scanf("%d %d", &N, &K); while (K--) { int i, ni; scanf("%d %d", &i, &ni); while (ni--) { string name; cin >> name; Data[name].push_back(i); } } while (N--) { string name; cin >> name; vector<int>& clist = Data[name]; printf("%s %lu", name.c_str(), clist.size()); sort(clist.begin(), clist.end()); for (size_t i = 0; i != clist.size(); ++i) { printf(" %d", clist[i]); } printf("\n"); } return 0;};
vector<int> selectCourse[26*26*26*10+1]
数组,用空间换时间; 这样修改后能轻松通过时间限制#include <vector>#include <algorithm>#include <cstdio>using namespace std;int N, K;vector<int> Data[26*26*26*10+1];int str_hash(char name[]){ int hash_res = 0; for (int i = 0; i < 3; ++i) { hash_res = hash_res * 26 + name[i] - 'A'; } hash_res = hash_res * 10 + name[3] - '0'; return hash_res;}int main(void){ scanf("%d %d", &N, &K); while (K--) { int i, ni; scanf("%d %d", &i, &ni); while (ni--) { char name[5]; scanf("%s", name); Data[str_hash(name)].push_back(i); } } while (N--) { char name[5]; scanf("%s", name); vector<int>& clist = Data[str_hash(name)]; sort(clist.begin(), clist.end()); printf("%s %lu", name, clist.size()); for (size_t i = 0; i != clist.size(); ++i) { printf(" %d", clist[i]); } printf("\n"); } return 0;};
#include <iostream>#include <string>#include <unordered_set>using namespace std;string original;string actual;unordered_set<char> broken;int main(int argc, const char* argv[]) { cin >> original >> actual; size_t original_idx = 0; for (size_t i = 0; i != actual.size(); ++i, ++original_idx) { while (original[original_idx] != actual[i]) { if (original[original_idx] >= 'a' && original[original_idx] <= 'z') { original[original_idx] += 'A' - 'a'; } if (broken.find(original[original_idx]) == broken.end()) { cout << original[original_idx]; broken.insert(original[original_idx]); } ++original_idx; } } for (; original_idx != original.size(); ++original_idx) { if (original[original_idx] >= 'a' && original[original_idx] <= 'z') { original[original_idx] += 'A' - 'a'; } if (broken.find(original[original_idx]) == broken.end()) { cout << original[original_idx]; broken.insert(original[original_idx]); } } return 0;}
#include <cstdio>#include <vector>#include <algorithm>using namespace std;// N 表示月饼的种类数 <= 1000 // D 表示市场最大需求量 <= 500int N;double D;int main(int argc, const char* argv[]) { scanf("%d %lf", &N, &D); vector<pair<double, double>> Value(N); // 价值、库存 double revenue = 0; for (int i = 0; i != N; ++i) { scanf("%lf", &Value[i].second); } for (int i = 0; i != N; ++i) { double price; scanf("%lf", &price); Value[i].first = price / Value[i].second; } sort(Value.begin(), Value.end(), [](const pair<double, double>& lhs, const pair<double, double>& rhs) -> bool { return lhs.first > rhs.first; });; for (int i = 0; i != N && D > 0; ++i) { int valid_weight = min(Value[i].second, D); D -= valid_weight; revenue += valid_weight * Value[i].first; } printf("%.2f", revenue); return 0;}
个人感觉这道题的解题方法用分治的思想更容易理解
50 1300 12 5 7.00 0 8.00 300 9.00 600 10.00 900 11.00 1200
#include <cstdio>#include <algorithm>#include <vector>using namespace std;double FullTankCapacity;double TotalDistance;double DAvg;size_t N;struct Station { double price; double distance;};vector<Station> Stations;double FullTankCapacityDis;double CheapestPrice = 0;double NowGasVolume = 0;int main(int argc, const char* argv[]) { scanf("%lf %lf %lf %lu", &FullTankCapacity, &TotalDistance, &DAvg, &N); FullTankCapacityDis = FullTankCapacity * DAvg; for (size_t i = 0; i != N; ++i) { Station tmp; scanf("%lf %lf", &tmp.price, &tmp.distance); if (tmp.distance >= TotalDistance) { continue; } Stations.push_back(std::move(tmp)); } N = Stations.size(); sort(Stations.begin(), Stations.end(), [](const Station& lhs, const Station& rhs) -> bool { return lhs.distance < rhs.distance; }); if (Stations[0].distance > 0) { printf("The maximum travel distance = 0.00"); return 0; } size_t now = 0; while (now + 1 < N) // now 后肯定有一个加油站, 不断寻找 now 的下一个要到达的加油站 { if (Stations[now + 1].distance - Stations[now].distance > FullTankCapacityDis) { break; } bool find_cheaper_station = false; // 如果在加油站 now 开始,有一个加油站距离在 FullTankCapacityDis 内,且油价更便宜,那么直接开到该加油站 for (size_t next = now + 1; next != N && Stations[next].distance - Stations[now].distance <= FullTankCapacityDis; ++next) { if (Stations[next].price <= Stations[now].price) { double ddis = Stations[next].distance - Stations[now].distance; if (NowGasVolume * DAvg < ddis) { // 需要加油 double dgas = (ddis - NowGasVolume * DAvg) / DAvg; NowGasVolume += dgas; CheapestPrice += dgas * Stations[now].price; now = next; } // 开到 next 加油站 NowGasVolume -= ddis / DAvg; now = next; find_cheaper_station = true; break; } } if(find_cheaper_station == false) { if (TotalDistance - Stations[now].distance <= FullTankCapacityDis) { // 可以一次到达终点,则直接开到终点即可,不用加满油 break; } // 不能一次到达终点,则油箱加满,开到 FullTankCapacityDis 内油价最便宜的加油站 double dgas = FullTankCapacity - NowGasVolume; NowGasVolume = FullTankCapacity; CheapestPrice += dgas * Stations[now].price; int min_idx = now + 1; double min_price = Stations[now + 1].price; for (size_t next = now + 2; next < N && Stations[next].distance - Stations[now].distance <= FullTankCapacityDis; ++next) { if (Stations[next].price < min_price) { min_price = Stations[next].price; min_idx = next; } } NowGasVolume -= (Stations[min_idx].distance - Stations[now].distance) / DAvg; now = min_idx; } } // 往后走不会再碰到加油站,因此直接看能不能开到终点即可 if (TotalDistance > Stations[now].distance + FullTankCapacityDis) { printf("The maximum travel distance = %.2f", Stations[now].distance + FullTankCapacityDis); } else { double ddis = TotalDistance - Stations[now].distance; double gas_needed = ddis / DAvg; if (NowGasVolume < gas_needed) { // 加油 CheapestPrice += gas_needed * Stations[now].price; } printf("%.2f", CheapestPrice); } return 0;}
2 03 030 // 应该输出 3003 而非 3030,但如果按照我的方法,03 和 030 是分不出大小的
#include <cstdio>#include <algorithm>#include <vector>using namespace std;int N;vector<vector<char>> Segs;bool cmp(const vector<char>& lhs, const vector<char>& rhs){ size_t min_size = min(lhs.size(), rhs.size()); for (size_t i = 0; i != min_size; ++i) { if (lhs[i] != rhs[i]) { return lhs[i] < rhs[i]; } } if (lhs.size() < rhs.size()) { return rhs[0] < rhs[min_size]; } else if (lhs.size() > rhs.size()) { return lhs[min_size] < lhs[0]; } else { // 两个数字段完全相等 return false; }}int main(int argc, const char* argv[]) { scanf("%d", &N); getchar(); while (N--) { vector<char> num; char tmp; while ((tmp = getchar()) != ' ' && tmp != '\n') { num.push_back(tmp); } Segs.push_back(num); } sort(Segs.begin(), Segs.end(), cmp); bool zero_flag = true; for (size_t i = 0; i != Segs.size(); ++i) { for (size_t j = 0; j != Segs[i].size(); ++j) { if (zero_flag && Segs[i][j] == '0') { continue; } else if(zero_flag){ zero_flag = false; } printf("%c", Segs[i][j]); } } if (zero_flag) { printf("0"); } return 0;}
#include <iostream>#include <algorithm>#include <string>#include <vector>using namespace std;int N;vector<string> Segs;string Res;int main(int argc, const char* argv[]) { cin >> N; while (N--) { string tmp; cin >> tmp; Segs.push_back(tmp); } sort(Segs.begin(), Segs.end(), [](const string& lhs, const string& rhs) -> bool { return lhs + rhs < rhs + lhs; }); for (size_t i = 0; i != Segs.size(); ++i) { Res += Segs[i]; } bool zero_flag = true; for (size_t i = 0; i != Res.size(); ++i) { if (zero_flag && Res[i] == '0') { continue; } else { zero_flag = false; } cout << Res[i]; } if (zero_flag) { cout << 0; } return 0;}
我在下面的代码中用的是
map
来记录所有错位数字及其位置,但感觉书上的方案更巧妙一些
#include <cstdio>#include <algorithm>#include <vector>#include <unordered_map>using namespace std;size_t N;vector<int> Perm;unordered_map<int, int> WrongPos; // 错误排列的数字及其位置int SwapCnt = 0;int main(int argc, const char* argv[]) { scanf("%lu", &N); for(size_t i = 0; i != N; ++i) { size_t tmp; scanf("%lu", &tmp); Perm.push_back(tmp); if (tmp != i) { WrongPos.insert({ tmp, i }); } } while (WrongPos.size() != 0) { if (WrongPos.find(0) == WrongPos.end()) // 0 在正确位置,则与另一个不在正确位置的数字互换位置 { auto wrong_pair = *(WrongPos.begin()); swap(Perm[0], Perm[wrong_pair.second]); ++SwapCnt; WrongPos.insert({ 0, wrong_pair.second }); WrongPos[wrong_pair.first] = 0; } else { // 0 不在正确位置,则将 Perm[0] 与 Perm[Perm[0]] 互换,使数字 Perm[0] 交换到正确位置 WrongPos.erase(Perm[0]); swap(Perm[0], Perm[Perm[0]]); ++SwapCnt; WrongPos[Perm[0]] = 0; if (WrongPos[0] == 0) // 正好 Perm[Perm[0]] 即为 0 { WrongPos.erase(0); } } } printf("%d", SwapCnt); return 0;}
// 这里截取了书上代码的关键部分,明显比我写的更简洁int k = 1; // k 存放除 0 以外当前不在本位上的最小的数while (left > 0) { // 只要还有数不在本位上 // 如果 0 在本位上, 则寻找一个当前不在本位上的数与 0 交换 if (pos[0] == 0) { while (k < n) { if (pos[k] != k) { // 找到一个当前不在本位上的数 k swap(pos[0], pos[k]); // 将 k 与 0 交换位置 ans++; // 交换次数加 1 break; // 退出循环 } k++; // 判断 k + l 是否在本位 } } // 只要 0 不在本位, 就将 0 所在位置的数的当前所处位置与 0 的位置交换 while (pos[0] != 0) { swap(pos[0], pos[pos[0]]); // 将0与pos[O]交换 ans++; // 交换次数加1 left--; // 不在本位上的数的个数减1 }}
int solve(int left, int right) { int mid; while (left < right) { // 注意:这里是 < 而非 <=,结束时一定为 low == high mid = (left + right) / 2; if (条件成立) { // 条件成立,第一个满足条件的元素的位置 <=mid right = mid; // 往左子区间 [left, mid] 查找 } else { // 条件不成立,则第一个满足该条件的元素的位置 >mid left = mid + 1; // 往右子区间 [mid+1, right] 查找 } } return left; // 返回夹出来的位置}
right
而非我们想要的 right + 1
,因此需要多加一个判断语句:如果最后一个元素也不满足条件,那么直接返回尾后位置int solve(int left, int right) { if (right 位置的元素不满足条件) { return right + 1; } int mid; while (left < right) { // 注意:这里是 < 而非 <=,结束时一定为 low == high mid = (left + right) / 2; if (条件成立) { // 条件成立,第一个满足条件的元素的位置 <=mid right = mid; // 往左子区间 [left, mid] 查找 } else { // 条件不成立,则第一个满足该条件的元素的位置 >mid left = mid + 1; // 往右子区间 [mid+1, right] 查找 } } return left; // 返回夹出来的位置}
equal_range
、lower_bound
和 upper_bound
算法返回迭代器, 指向给定元素在序列中的正确插入位置----插入后还能保持有序。如果给定元素比序列中的所有元素都大, 则会返回尾后迭代器x
小于 y
" 表示 x<y
或 comp(x,y)
成功lower_bound(beg, end, val)lower_bound(beg, end, val, comp)
val
的元素,如果不存在这样的元素,则返回 end
upper_bound(beg, end, val)upper_bound(beg, end, val, comp)
val
的元素, 如果不存在这样的元素, 则返回 end
equal_range(beg, end, val)equal_range(beg, end, val, comp)
pair
, 其 first
成员是 lower_bound
返回的迭代器, second
成员是 upper_bound
返回的迭代器binary_search(beg, end, val)binary_search(beg, end, val, comp)
bool
值, 指出序列中是否包含等于 val
的元素。对于两个值 x x x 和 y y y,当 x x x 不小于 y y y 且 y y y 也不小于 x x x 时, 认为它们相等#include <iostream>#include <algorithm>#include <vector>using namespace std;vector<int> limbs{ 10, 24, 15};int K = 7;bool valid(int len){ int sum = 0; for (const auto& limb : limbs) { sum += limb / len; } return sum < K;}int solve(int left, int right){ int mid; while (left < right) { mid = (left + right) / 2; if (valid(mid)) { right = mid; } else { left = mid + 1; } } return left;}int main(int argc, const char* argv[]) { cout << solve(0, *max_element(limbs.begin(), limbs.end())) - 1; return 0;}
参考:
#include <stdio.h>// 求弧度double getTotalRadian(double edges[],int n,double r){ double radian = 0.0; for(int i = 0; i < n; i++) radian += asin(edges[i] / 2 / r) * 2; return radian;}// 二分查找求最大半径void maxR(){ // 错误率 double error = 1e-5; // 边的个数 int n; // 边长数组 double edges[5000]; // 弧度 最大边 π double radian, maxEdge = 0.0, pi = asin(-1); // 初始化 edges scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%lf", &edges[i]); if(edges[i] > maxEdge) maxEdge = edges[i]; } //若最长边为直径,则直接处理 radian = getTotalRadian(edges, n, maxEdge/2); if(abs(radian-pi*2)<error) { printf("外接圆的最大半径是:%.2f",maxEdge/2); return; } double left =0,right=10000000,mid; //在误差范围内循环求解 while(right -left >error) { mid = (right + left) / 2; radian = getTotalRadian(edges, n, mid); if(radian > 2 * pi) left = mid; else right = mid; } printf("外接圆的最大半径是:%.2f",mid); }}
typedef long long LL;LL pow(LL a, LL b, LL m) { LL ans= 1; for(int i = 0; i < b; i++) { ans = ans * a % m; } return ans;}
typedef long long LL;// 递归写法LL binaryPow(LL a, LL b, LL m) { if (b == 0) return 1; // b 为奇数,转换为 b-1 if(b % 2 == 1) return a * binaryPow(a, b - 1, m) % m; else ( // b 为偶数,转换为 b/2 LL mul = binaryPow(a, b / 2, m); return mul * mul % m; }}
ans
等于 1, 用来存放累积的结果b
的二进制末尾是否为 1, 如果是的话, 令 ans
乘上 a
的值a
平方, 并将 b
右移一位b
大于 0, 就返回 (2)typedef long long LL;LL binaryPow(LL a, LL b, LL rn) { LL ans = 1; while (b > 0) { if (b & 1) { ans = ans * a % m; } a = a * a % m; b >>= 1; } return ans;}
long long
类型。同时, 题目也没有说明 radix
的范围,这可能是一个很大的数,因此必须在计算过程中判断是否溢出。特别地, 数据默认保证已知进制的那个数在转换成十进制时不超过 long long
(是的, 题中没有说!), 因此只需要对未知进制的数在转换成十进制时判断是否溢出(只要在转换过程中某步小于 0 即为溢出)N2
进制的下界为所有数位中最大的那个加 1, 上界为下界与 N1
值的较大值加 1 (假设已知的是 N1
的进制)#include <iostream>#include <algorithm>#include <string>using namespace std;size_t digit_to_val(const char& c){ if (c >= 'a' && c <= 'z') { return c - 'a' + 10; } else { return c - '0'; }}long long num_to_val(const string& s, long long radix){ long long val = 0; for (auto it = s.begin(); it != s.end(); ++it) { val = val * radix + digit_to_val(*it); if (val < 0) // 判断是否溢出 { return -1; } } return val;}int cmp(const string& lhs, long long radix, long long rhs){ long long lhs_val = num_to_val(lhs, radix); if (lhs_val < 0) { return 1; // lhs 溢出,lhs 更大 } if (rhs > lhs_val) { return -1; } else if (rhs == lhs_val) { return 0; } else { return 1; }}int main(int argc, const char* argv[]) { string N1, N2; int tag; long long radix; cin >> N1 >> N2 >> tag >> radix; if (tag == 2) { swap(N1, N2); } long long val = num_to_val(N1, radix); size_t low = 0, high, mid; for (const auto& c : N2) { size_t d = digit_to_val(c); if (d > low) { low = d; } } low += 1; high = max((long long)low, val); while (low < high) { mid = low + (high - low) / 2; if (cmp(N2, mid, val) >= 0) { high = mid; } else { low = mid + 1; } } if (cmp(N2, low, val) != 0) { cout << "Impossible"; } else { cout << low; } return 0;}
#include <cstdio>#include <vector>#include <algorithm>using namespace std;int N, M;vector<int> Sum;int MinVal;vector<pair<int, int>> Res;int main(int argc, const char* argv[]) { scanf_s("%d %d", &N, &M); Sum.resize(N + 1); for (int i = 1; i <= N; ++i) { scanf_s("%d", &Sum[i]); Sum[i] += Sum[i - 1]; } MinVal = Sum[N]; for (int i = 1; i <= N; ++i) { int low = i, high = N, mid; while (low < high) { mid = low + (high - low) / 2; if (Sum[mid] - Sum[i - 1] >= M) { high = mid; } else { low = mid + 1; } } int tmp_sum = Sum[low] - Sum[i - 1]; if (tmp_sum >= M && tmp_sum <= MinVal) { if (tmp_sum < MinVal) { Res.clear(); MinVal = tmp_sum; } Res.push_back({ i, low }); } } for (const auto& res : Res) { printf("%d-%d\n", res.first, res.second); } return 0;}
unordered_map
来做,也可以用 two pointers 来做#include <cstdio>#include <unordered_map>#include <vector>#include <algorithm>using namespace std;unordered_map<int, int> Coins;vector<int> VCoins;int main(int argc, const char* argv[]) { int N, M; scanf("%d %d", &N, &M); while (N--) { int tmp; scanf("%d", &tmp); Coins[tmp] += 1; VCoins.push_back(tmp); } sort(VCoins.begin(), VCoins.end()); for (const auto& coin : VCoins) { --Coins[coin]; if (Coins[M - coin] >= 1) { printf("%d %d", coin, M - coin); return 0; } ++Coins[coin]; } printf("No Solution"); return 0;}
二分法 O ( n log n ) O(n\log n) O(nlogn)
#include <cstdio>#include <algorithm>#include <vector>using namespace std;vector<double> Seq;size_t MaxCnt = 0;int N;int main(int argc, const char* argv[]) { double p; scanf("%d %lf", &N, &p); while (N--) { double tmp; scanf("%lf", &tmp); Seq.push_back(tmp); } sort(Seq.begin(), Seq.end()); for (size_t m = 0; m < Seq.size() - MaxCnt; ++m) { size_t low = m, high = Seq.size() - 1; size_t mid; if (Seq.back() <= Seq[m] * p) { low = Seq.size(); } else { while (low < high) { mid = low + (high - low) / 2; if (Seq[mid] > Seq[m] * p) { high = mid; } else { low = mid + 1; } } } size_t cnt = low - m; if (cnt > MaxCnt) { MaxCnt = cnt; } } printf("%lu", MaxCnt); return 0;}
// 也可使用 upper_bound#include <cstdio>#include <algorithm>#include <vector>using namespace std;vector<double> Seq;size_t MaxCnt = 0;int N;int main(int argc, const char* argv[]) { double p; scanf("%d %lf", &N, &p); while (N--) { double tmp; scanf("%lf", &tmp); Seq.push_back(tmp); } sort(Seq.begin(), Seq.end()); for (size_t m = 0; m < Seq.size() - MaxCnt; ++m) { size_t cnt = upper_bound(Seq.begin(), Seq.end(), Seq[m] * p) - Seq.begin() - m; if (cnt > MaxCnt) { MaxCnt = cnt; } } printf("%lu", MaxCnt); return 0;}
Partition
的实现,都可以归为 two pointers 思想找到链表中间位置的结点
(low + high + 1) / 2
得出#include <cstdio>#include <algorithm>#include <vector>using namespace std;size_t N;vector<long long> s1;vector<long long> s2;int main(int argc, const char* argv[]){ scanf("%lu", &N); s1.resize(N); for (size_t i = 0; i != N; ++i) { scanf("%lld", &s1[i]); } scanf("%lu", &N); s2.resize(N); for (size_t i = 0; i != N; ++i) { scanf("%lld", &s2[i]); } size_t mid_pos = (s1.size() + s2.size() + 1) / 2; // 计算中位数位置 size_t i = 0, j = 0, cnt = 0; long long ans; while (cnt < mid_pos && i < s1.size() && j < s2.size()) { ++cnt; if (s1[i] < s2[j]) { ans = s1[i]; ++i; } else { ans = s2[j]; ++j; } } if (cnt < mid_pos && i < s1.size()) { ans = s1[i + mid_pos - cnt - 1]; // 最后位置可以直接计算得出,没必要用循环 } if (cnt < mid_pos && j < s2.size()) { ans = s2[j + mid_pos - cnt - 1]; } printf("%lld", ans); return 0;}
two pointers O ( n ) O(n) O(n)
a[j] <= a[i] * p
成立, 那么对 [i,j]
内的任意位置 k
, 一定有 a[k] <= a[i] * p
也成立。这种有序序列的性质就引导我们往 two pointers 思想去考虑, 如此可以得到以下时间复杂度为 O ( n ) O(n) O(n) 的算法: i
、j
的初值均为 0, 表示 i
、j
均指向有序序列的第一个元素, 并设置计数器 count
存放满足 a[j] <= a[i] * p
的最大长度。接下来让 j
不断增加, 直到不等式 a[j] <= a[i] * p
恰好不成立为止(在此过程中更新 count
)。之后让下标 i
右移一位,并继续上面让 j
不断增加的操作, 以此类推, 直到 j
到达序列末端。这个操作的目的在于,在 a[j] <= a[i] * p
的条件下始终控制 i
和 j
的距离最大#include <cstdio>#include <algorithm>#include <vector>using namespace std;vector<double> Seq;size_t MaxCnt = 0;int N;int main(int argc, const char* argv[]){ double p; scanf("%d %lf", &N, &p); Seq.resize(N); for(size_t i = 0; i != N; ++i) { scanf("%lf", &Seq[i]); } sort(Seq.begin(), Seq.end()); size_t m = 0, M = 0; for (; m < Seq.size() - MaxCnt; ++m) { while (M != Seq.size() && Seq[M] <= Seq[m] * p) { ++M; } MaxCnt = max(MaxCnt, M - m); } printf("%lu", MaxCnt); return 0;}
sort
代替的;其实在不超时的情况下,Merge
也可以用 sort
代替#include <cstdio>#include <algorithm>#include <vector>using namespace std;int N;vector<double> Raw, Partial;void Merge(vector<double>& src, vector<double>& dst, size_t beg, size_t mid, size_t end){ size_t n = end - beg + 1; size_t beg2 = mid + 1; size_t dst_cnt = beg; while (beg <= mid && beg2 <= end) { if (src[beg] < src[beg2]) { dst[dst_cnt++] = src[beg++]; } else { dst[dst_cnt++] = src[beg2++]; } } while (beg <= mid) { dst[dst_cnt++] = src[beg++]; } while (beg2 <= end) { dst[dst_cnt++] = src[beg2++]; }}void MergePass(vector<double>& src, vector<double>& dst, int len){ size_t n = src.size(); size_t i = 0; for (; i + 2 * len - 1 < n; i += 2 * len) { Merge(src, dst, i, i + len - 1, i + 2 * len - 1); } if (i + len < n) { Merge(src, dst, i, i + len - 1, n - 1); } else { while (i < n) { dst[i] = src[i]; ++i; } }}int main(int argc, const char* argv[]){ scanf_s("%d", &N); Raw.resize(N); Partial.resize(N); for (size_t i = 0; i != N; ++i) { scanf_s("%lf", &Raw[i]); } for (size_t i = 0; i != N; ++i) { scanf_s("%lf", &Partial[i]); } bool insert_flag = true; size_t i = 1; for (; i < N; ++i) { if (Partial[i] < Partial[i - 1]) { break; } } for (size_t j = i; j < N; ++j) { if (Partial[j] != Raw[j]) { insert_flag = false; break; } } if (!insert_flag) { size_t len = 1; vector<double> tmp(N); while (len < N) { MergePass(Raw, tmp, len); len *= 2; if (tmp == Partial) { MergePass(tmp, Partial, len); break; } MergePass(tmp, Raw, len); len *= 2; if (Raw == Partial) { MergePass(Raw, Partial, len); break; } } printf("Merge Sort\n"); } else { sort(Partial.begin(), Partial.begin() + i + 1); printf("Insertion Sort\n"); } for (size_t i = 0; i != Partial.size(); ++i) { printf("%.0f", Partial[i]); if (i + 1 != Partial.size()) { printf(" "); } } return 0;}
#include <cstdio>#include <vector>#include <algorithm>using namespace std;int N;vector<int> num;vector<int> pivot;int LMax;vector<int> RMin; // 每个位置对应的右边的最小值int main(int argc, const char* argv[]){ scanf("%d", &N); num.resize(N); RMin.resize(N); for (size_t i = 0; i != N; ++i) { scanf("%d", &num[i]); } LMax = num.front(); for (int i = N - 1; i >= 0; --i) { if (i != N - 1) { RMin[i] = min(RMin[i + 1], num[i]); } else { RMin[i] = num[i]; } } for (size_t i = 0; i != N; ++i) { if (num[i] >= LMax && num[i] <= RMin[i]) { pivot.push_back(num[i]); } LMax = max(LMax, num[i]); } if (pivot.size() == 0) { printf("0\n\n"); } else { printf("%lu\n", pivot.size()); sort(pivot.begin(), pivot.end()); for (size_t i = 0; i != pivot.size(); ++i) { printf("%d", pivot[i]); if (i + 1 != pivot.size()) { printf(" "); } else { printf("\n"); } } } return 0;}
转载地址:http://mmih.baihongyu.com/