L2-001 紧急救援 (25 分)
L2-002 链表去重 (25 分)
#include<bits/stdc++.h>
#define PIS pair <int, string>
#define val first
#define ne second
using namespace std;
const int N = 1e6+10;
map<string, PIS> Map;
string st_address;
int n, st[N];
vector <string> v;
int main()
{
cin >> st_address >> n;
for (int i = 0;i < n;i ++) {
string ad, ne;
int val;
cin >> ad >> val >> ne;
Map[ad] = {val, ne};
}
string p = st_address;
while (p != "-1") {
st[abs(Map[p].val)] = 1;
string t = Map[p].ne;
while (t != "-1") {
if (st[abs(Map[t].val)])
v.push_back (t);
else
break;
t = Map[t].ne;
}
Map[p].ne = t;
cout << p << ' ' << Map[p].val << ' ' << Map[p].ne << endl;
p = t;
}
int len = v.size()-1; // 不能直接用i < v.size()-1,段错误,不知道为什么
for (int i = 0;i < len;i ++)
cout << v[i] << ' ' << Map[v[i]].val << ' ' << v[i+1] << endl;
if (v.size() > 0) cout << v[v.size()-1] << ' ' << Map[v[v.size()-1]].val << ' ' << -1 << endl;
return 0;
}
L2-004 这是二叉搜索树吗? (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1100;
int n, a[N];
vector <int> v;
void dfs (int l, int r, int mir) {
if (l > r) return ;
int rt = a[l];
int p = l+1, q = l+1;
if (!mir) { // 非镜像
while (p <= r && a[p] < rt) p ++, q ++; // 找到第一个大于等于根节点的,也就是右子树的开头
while (q <= r && a[q] >= rt) q ++; // 找到右子树的结尾的后一个
} else {
while (p <= r && a[p] >= rt) p ++, q ++;
while (q <= r && a[q] < rt) q ++;
}
dfs (l+1, p-1, mir);
dfs (p, q-1, mir);
v.push_back (rt); // 直接按照后续遍历的顺序保存;先dfs左右子树后再将根节点加入v中;如果中序遍历,只需要改变push_back语句与dfs语句的次序即可
}
void print () {
puts ("YES");
cout << v[0];
for (int i = 1;i < v.size();i ++)
cout << ' ' << v[i];
}
int main()
{
int n;
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
dfs (1, n, 0);
if (v.size () == n) { // 如果v中包含了n个元素,说明n个数全部加入
print ();
return 0;
}
v.clear ();
dfs (1, n, 1);
if (v.size() == n) print ();
else puts ("NO");
return 0;
}
L2-003 月饼 (25 分)
贪心而已,按照性价比排序。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int n;
double D, ans = 0;
struct node {
double a, b, c;
} yb[N];
bool cmp (node a, node b) {
return a.c > b.c;
}
int main()
{
cin >> n >> D;
for (int i = 0;i < n;i ++) cin >> yb[i].a;
for (int i = 0;i < n;i ++) cin >> yb[i].b, yb[i].c = 1.0 * yb[i].b / yb[i].a;
sort (yb, yb+n, cmp);
for (int i = 0;i < n && D;i ++) {
if (D >= yb[i].a) {
D -= yb[i].a;
ans += yb[i].b;
} else {
ans += D * yb[i].c;
break;
}
}
printf ("%.2f\n", ans); // 原来可以直接这样控制保留小数 // 这我都忘记了
return 0;
}
L2-005 集合相似度 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n, m;
set <string> s[N];
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) {
cin >> m;
while (m --) {
string str;
cin >> str;
s[i].insert (str);
}
}
cin >> m;
while (m --) {
int a, b, nc = 0, nt = 0;
cin >> a >> b;
for (auto i : s[a])
if (s[b].find (i) != s[b].end ())
nc ++;
nt = s[a].size () + s[b].size () - nc;
printf ("%.2lf\%\n", 100.0 * nc / nt);
}
return 0;
}
L2-006 树的遍历 (25 分)
#include<bits/stdc++.h>
using namespace std;
vector <int> v;
int a[50], b[50], n, left_val[50], right_val[50];
int dfs (int l1, int r1, int l2, int r2) {
if (l1 > r1 || l2 > r2) return 0;
int root = a[r1], p = l2;
while (p <= r2) {
if (b[p] == root) break;
p ++;
}
int left_sum = p - l2;
left_val[root] = dfs (l1, l1+left_sum-1, l2, p-1); // left_subtree
right_val[root] = dfs (l1+left_sum, r1-1, p+1, r2); // right_subtree
return root;
}
void bfs (int x) {
queue <int> q;
q.push (x);
while (q.size ()) {
int t = q.front ();
q.pop ();
v.push_back (t);
if (left_val[t]) q.push (left_val[t]);
if (right_val[t]) q.push (right_val[t]);
}
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
for (int i = 1;i <= n;i ++) cin >> b[i];
dfs (1, n, 1, n);
bfs (a[n]);
cout << v[0];
for (int i = 1;i < v.size();i ++)
cout << ' ' << v[i];
return 0;
}
L2-008 最长对称子串 (25 分)
一开始想二分判断,结果发现并不可行,比如:abba
,长度为3的时候是不行的,但长度为4的时候是可行的。
#include<bits/stdc++.h>
using namespace std;
string s;
int main()
{
getline (cin, s);
for (int len = s.size();len > 0;len --) {
for (int j = 0;j < s.size()-len+1;j ++) {
string ss = s.substr (j, len);
int l = 0, r = ss.size()-1;
while (l < r) {
if (ss[l] == ss[r]) l ++, r --;
else break;
}
if (l >= r) {
cout << len << endl;
return 0;
}
}
}
return 0;
}
L2-009 抢红包 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
struct node {
int id, num, money;
} info[N];
bool cmp (node a, node b) {
if (a.money != b.money) return a.money > b.money;
if (a.num != b.num) return a.num > b.num;
return a.id < b.id;
}
int main()
{
int n;
cin >> n;
for (int i = 1;i <= n;i ++) {
info[i].id = i; // ! // 样例中的编号6只发不收,如果没有这句话其id一直为0
int k;
cin >> k;
while (k --) {
int id, money;
cin >> id >> money;
info[id].id = id;
info[id].num ++;
info[id].money += money;
info[i].money -= money;
}
}
sort (info+1, info+n+1, cmp);
for (int i = 1;i <= n;i ++) {
printf ("%d %.2lf\n", info[i].id, info[i].money / 100.0);
}
return 0;
}
L2-010 排座位 (25 分)
并查集的用法。
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
bool duili[N][N];
int fa[N];
int find (int x) {
return x == fa[x] ? fa[x] : fa[x] = find (fa[x]);
}
void join (int x, int y) {
int rx = find (x), ry = find (y);
if (rx != ry) fa[rx] = ry;
}
int main()
{
int n, m, k;
int a, b, re;
cin >> n >> m >> k;
for (int i = 0;i <= 100;i ++) fa[i] = i;
while (m -- ) {
cin >> a >> b >> re;
if (re == -1)
duili[a][b] = duili[b][a] = true;
else
join (a, b);
}
while (k -- ) {
cin >> a >> b;
int ra = find (a), rb = find (b);
bool bool1 = (ra == rb), bool2 = duili[a][b];
if (bool1 && !bool2) cout << "No problem" << endl;
else if (!bool1 && !bool2) cout << "OK" << endl;
else if (bool1 && bool2) cout << "OK but..." << endl;
else cout << "No way" << endl;
}
return 0;
}
L2-011 玩转二叉树 (25 分)
和上面的第六题几乎一样。
#include<bits/stdc++.h>
using namespace std;
const int N = 50;
int n, a[N], b[N];
int right_subtree_root[N<<1], left_subtree_root[N<<1];
int dfs (int l1, int r1, int l2, int r2) {
if (l1 > r1 || l2 > r2) return 0;
int rt = b[l2];
int p = l1;
while (p <= r1 && a[p] != rt) p ++;
right_subtree_root[rt] = dfs (l1, p-1, l2+1, l2+p-l1); // 镜像,dfs左子树,但是赋值给rt的右子树数组
left_subtree_root[rt] = dfs (p+1, r1, l2+p-l1+1, r2); // 前序遍历数组左子树和右子树索引范围的判定,是根据中序遍历得到左子树元素个数和右子树元素个数
return rt;
}
void bfs (int x) {
vector <int> v;
queue <int> q;
q.push (x);
while (q.size()) {
int t = q.front ();
v.push_back (t);
q.pop ();
if (left_subtree_root[t]) q.push (left_subtree_root[t]); // 因为在dfs时已经进行过镜像操作了,所以这里就先左子树数组再右子树数组
if (right_subtree_root[t]) q.push (right_subtree_root[t]);
}
cout << v[0] ;
for (int i = 1;i < v.size();i ++) cout << ' ' << v[i];
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i]; // mid
for (int i = 1;i <= n;i ++) cin >> b[i]; // before
dfs (1, n, 1, n);
bfs (b[1]);
return 0;
}
L2-012 关于堆的判断 (25 分)
首先要知道堆插入元素的更新原理;还要利用二叉树索引的特点。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n, m, idx;
int tr[N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++) {
int x;
cin >> x;
tr[++ idx] = x;
int t = idx;
while (t != 1) {
if (tr[t>>1] > tr[t]) swap (tr[t>>1], tr[t]), t >>= 1;
else break;
}
}
while (m --) {
int a = 0, b = 0, op;
cin >> a;
string s;
while (cin >> s) {
if (s == "root") {
op = 1;
break;
} else if (s == "and") {
cin >> b >> s >> s;
op = 2;
break;
} else if (s == "parent") {
cin >> s >> b;
op = 3;
break;
} else if (s == "child") {
cin >> s >> b;
op = 4;
break;
}
}
if (op == 1) {
if (a == tr[1]) puts ("T");
else puts ("F");
} else {
int idx_a = 0, idx_b = 0;
for (int i = 1;i <= idx;i ++)
if (tr[i] == a) idx_a = i;
else if (tr[i] == b) idx_b = i;
if (op == 2 && ((idx_a>>1) == (idx_b>>1))) puts ("T");
else if (op == 3 && (idx_a == (idx_b>>1))) puts ("T");
else if (op == 4 && (idx_b == (idx_a>>1))) puts ("T");
else puts ("F");
}
}
return 0;
}
L2-013 红色警报 (25 分)
并查集。
每次删除一座城市就将其标记一下,每删除一座城市,就使用全部关系(除了被标记的城市)重新构件连通块,判断连通分支数是否比删除该城市前的连通分支数大,如果前者大说明改变了连通性。当连通分支数为0时,说明没有城市了,game over。
#include<bits/stdc++.h>
using namespace std;
const int N = 600, M = 5010;
int fa[N], st[N], a[M], b[M];
int find (int x) {
return x == fa[x] ? fa[x] : fa[x] = find (fa[x]);
}
void join (int x, int y) {
int rx = find (x), ry = find (y);
if (rx != ry) fa[rx] = ry;
}
int main()
{
int n, m, c, k, cnt_unit = 0, loss = 0;
cin >> n >> m;
for (int i = 0;i < n;i ++) fa[i] = i;
for (int i = 0;i < m;i ++) {
cin >> a[i] >> b[i];
join (a[i], b[i]);
}
cin >> k;
for (int i = 0;i < n;i ++)
if (fa[i] == i)
cnt_unit ++;
while (k -- ) {
cin >> c;
st[c] = 1;
loss ++;
for (int i = 0;i < n;i ++) fa[i] = i;
for (int i = 0;i < m;i ++)
if (!st[a[i]] && !st[b[i]])
join (a[i], b[i]);
int cnt = 0;
for (int i = 0;i < n;i ++)
if (!st[i] && fa[i] == i)
cnt ++;
if (cnt > cnt_unit) printf ("Red Alert: City %d is lost!\n", c);
else printf ("City %d is lost.\n", c);
if (cnt == 0) cout << "Game Over." << endl;
cnt_unit = cnt;
}
return 0;
}
L2-014 列车调度 (25 分)
本质是贪心。
但是这个题的贪心思路与计算最长上升子序列的贪心思路是一样的,所以直接使用最长上升子序列的优化模板。
还不理解可以看yxc的课程,有一节课讲过(不是这道题,而是贪心思路)(动态规划章节)。
#include<bits/stdc++.h>
using namespace std;
int n, ans, a[100010], d[100010], len;
int erfen (int x) {
int l = 1, r = len, mid;
while (l < r) {
mid = l + r >> 1;
if (d[mid] >= x) r = mid;
else l = mid + 1;
}
return l;
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
for (int i = 1;i <= n;i ++) {
if (a[i] > d[len]) d[++len] = a[i];
else d[erfen (a[i])] = a[i]; // 等价于 d[lower_bound(d+1, d+len+1, a[i]) - d] = a[i]
}
cout << len << endl;
return 0;
}
L2-015 互评成绩 (25 分)
太欣慰了,L2居然有签到!
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
vector <double> v;
int n, k, m;
int s[10010][20];
int main()
{
cin >> n >> k >> m;
for (int i = 1;i <= n;i ++) {
int mx = 0;
int mn = INF;
int sum = 0;
for (int j = 1;j <= k;j ++) {
cin >> s[i][j];
mx = max (mx, s[i][j]);
mn = min (mn, s[i][j]);
sum += s[i][j];
}
v.push_back (1.0 * (sum - mx - mn) / (k - 2));
}
sort (v.begin(), v.end());
printf ("%.3lf", v[v.size()-m]);
for (int i = v.size()-m+1;i < v.size();i ++)
printf (" %.3lf", v[i]);
return 0;
}
L2-016 愿天下有情人都是失散多年的兄妹 (25 分)
L2-017 人以群分 (25 分)
先保证人数最小差距,再保证和的最大差距。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int diff, l_num, r_num = N, a[N], b[N], sum;
int n;
int main () {
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i], sum += a[i];
sort (a + 1, a + n + 1);
for (int i = 1;i <= n;i ++) {
b[i] = b[i-1] + a[i];
int r_sum = sum - b[i];
int l_sum = b[i];
int t_left = i, t_right = n - i;
if (abs (t_right - t_left) < abs (l_num - r_num))
l_num = t_left, r_num = t_right, diff = r_sum - l_sum;
else if (abs (t_right - t_left) == abs (l_num - r_num)) {
if (r_sum - l_sum > diff) {
diff = r_sum - l_sum;
l_num = i;
r_num = n - i;
}
}
}
cout << "Outgoing #: " << r_num << endl;
cout << "Introverted #: " << l_num << endl;
cout << "Diff = " << diff << endl;
}
L2-019 悄悄关注 (25 分)
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
int n, m, sum, cnt;
string name;
set <string> s;
vector <string> v;
map <string, int> click;
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) {
cin >> name;
s.insert (name);
}
cin >> m;
for (int i = 1;i <= m;i ++) {
cin >> name >> cnt;
click.insert ({name, cnt});
sum += cnt;
}
double avg = 1.0 * sum / m;
for (auto item : click) {
name = item.x;
cnt = item.y;
if (cnt > avg && s.find (name) == s.end ())
v.push_back (name);
}
if (v.size () == 0) puts("Bing Mei You");
else {
sort (v.begin (), v.end ());
for (auto i : v) cout << i << endl;
}
return 0;
}
L2-020 功夫传人 (25 分)
DFS。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int ddz[N];
double z, r, ans, bili;
int e[N<<1], ne[N<<1], h[N], idx;
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs (int x, double g) {
if (ddz[x]) ans += g * ddz[x];
for (int i = h[x];~i;i = ne[i]) {
int j = e[i];
dfs (j, g * bili);
}
}
int main()
{
memset (h, -1, sizeof h);
cin >> n >> z >> r;
for (int i = 0;i < n;i ++) {
int k;
cin >> k;
if (k == 0) {
cin >> ddz[i];
} else {
while (k --) {
int u;
cin >> u;
add (i, u);
}
}
}
bili = (100.0 - r) / 100.0;
dfs (0, z); // 祖师爷也可能是得道者
cout << int (ans) << endl;
return 0;
}
L2-021 点赞狂魔 (25 分)
#include<bits/stdc++.h>
using namespace std;
set <int> s;
struct people {
string name;
int sum;
int dif;
} peo[110];
bool cmp (people a, people b) {
if (a.dif != b.dif) return a.dif > b.dif;
return (1.0 * a.dif / a.sum) > (1.0 * b.dif / b.sum);
}
int main()
{
int n;
cin >> n;
for (int i = 1;i <= n;i ++) {
cin >> peo[i].name >> peo[i].sum;
s.clear ();
for (int j = 1;j <= peo[i].sum;j ++) {
int pass;
cin >> pass;
s.insert (pass);
}
peo[i].dif = s.size();
}
sort (peo + 1, peo + n + 1, cmp);
if (n == 0) cout << "- - -" << endl;
else if (n == 1) cout << peo[1].name << " - -" << endl;
else if (n == 2) cout << peo[1].name << ' ' << peo[2].name << " -" << endl;
else cout << peo[1].name << ' ' << peo[2].name << ' ' << peo[3].name << endl;
return 0;
}
L2-022 重排链表 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct Node {
int val, next, pre;
} node[N];
int start_address, n;
int main()
{
cin >> start_address >> n;
for (int i = 1;i <= n;i ++) {
int a, b, c;
cin >> a >> b >> c;
node[a].val = b;
node[a].next = c;
node[c].pre = a;
}
int p = start_address, end_address = start_address, cnt = 0;
while (p != -1) {
end_address = p;
p = node[p].next;
cnt ++;
}
n = cnt; // 更新n为链路上的节点数
for (int i = 1;i <= (n-1)/2;i ++) { // 仅执行前面若干步,到达边界的输出单独判断
// 先打印右边的
printf ("%05d %d %05d\n", end_address, node[end_address].val, start_address);
end_address = node[end_address].pre;
// 再打印左边的
printf ("%05d %d %05d\n", start_address, node[start_address].val, end_address);
start_address = node[start_address].next;
}
if (n & 1) { // 最后一步是显示右边,记得输出-1
printf ("%05d %d -1\n", end_address, node[end_address].val);
} else { // 先显示右边,再显示左边,记得输出-1
printf ("%05d %d %05d\n", end_address, node[end_address].val, start_address);
printf ("%05d %d -1\n", start_address, node[start_address].val);
}
return 0;
}
/*
// n = cnt;
00100 3
00100 4 00000
00000 1 -1
68237 6 00000
*/
L2-023 图着色问题 (25 分)
注意三点:
- 判断相邻点是否同色,不用深搜、宽搜的,直接遍历每个点的临边即可;
- 上色颜色必须为k,大于小于都不行;
- 使用邻接表存边时,需要开数组到2e6,否则最后一个测试点死活过不去.
#include<bits/stdc++.h>
using namespace std;
const int N = 1000, M = 2e6+10;
vector<vector<int>> v(N);
int V, E, K, n;
int st[N], color[N];
int e[M], ne[M], h[N], idx;
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool check (int x) {
for (int i = h[x];~i;i = ne[i]) {
int j = e[i];
if (color[j] == color[x]) return false;
}
// for(int j = 0; j < v[x].size(); j++)
// if(color[x] == color[v[x][j]]) return false;
return true;
}
int main()
{
memset (h, -1, sizeof h);
cin >> V >> E >> K;
while (E --) {
int a, b;
cin >> a >> b;
add (a, b);
add (b, a);
// v[a].push_back(b);
// v[b].push_back(a);
}
cin >> n;
while (n --) {
set <int> s;
for (int i = 1;i <= V;i ++)
cin >> color[i],
s.insert (color[i]);
if (s.size () != K)
puts ("No");
else {
int flag = 0;
for (int i = 1;i <= V;i ++) {
if (!check (i)) {
flag = 1;
break;
}
}
if (flag) puts ("No");
else puts ("Yes");
}
}
return 0;
}
L2-024 部落 (25 分)
并查集。
每次用小圈子的第一个人与剩下的人join即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n, k, a, b, sum, dif;
int fa[N], st[N];
int find (int x) {
return fa[x] == x ? fa[x] : fa[x] = find (fa[x]);
}
int main()
{
cin >> n;
for (int i = 0;i < N;i ++) fa[i] = i;
while (n --) {
cin >> k >> a;
st[a] = 1;
for (int i = 1;i < k;i ++) { // 除去第一个还剩k-1个
cin >> b;
st[b] = 1;
int ra = find (a), rb = find (b);
if (ra != rb) fa[ra] = rb;
}
}
for (int i = 1;i < N;i ++)
if (st[i]) {
sum ++;
if (fa[i] == i) dif ++;
}
cout << sum << ' ' << dif << endl;
cin >> k;
while (k --) {
cin >> a >> b;
int ra = find (a), rb = find (b);
if (ra == rb) puts ("Y");
else puts ("N");
}
return 0;
}
L2-025 分而治之 (25 分)
和前面的红色警报是一个原理。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n, m;
int st[N], a[N], b[N], fa[N];
int find (int x) {
return fa[x] == x ? fa[x] : fa[x] = find (fa[x]);
}
void join (int x, int y) {
int rx = find (x), ry = find (y);
if (rx != ry) fa[rx] = ry;
}
bool check () {
for (int i = 1;i <= n;i ++)
if (!st[i])
if (fa[i] != i)
return false;
return true;
}
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++) fa[i] = i;
for (int i = 1;i <= m;i ++) {
cin >> a[i] >> b[i];
join (a[i], b[i]);
}
int k;
cin >> k;
while (k --) {
memset (st, 0, sizeof st);
int p;
cin >> p;
while (p --) {
int city;
cin >> city;
st[city] = 1;
}
for (int i = 1;i <= n;i ++) fa[i] = i;
for (int i = 1;i <= m;i ++) {
int c1 = a[i], c2 = b[i];
if (!st[c1] && !st[c2])
join (c1, c2);
}
if (check ()) puts ("YES");
else puts ("NO");
}
return 0;
}
L2-026 小字辈 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, rt, mx, dp[N];
int e[N<<1], ne[N<<1], h[N], idx;
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void bfs (int x) {
queue<int> q;
q.push (x);
dp[x] = 1;
while (q.size ()) {
int t = q.front ();
q.pop ();
mx = max (mx, dp[t]); // 放在for里面会少只有根节点的情况
for (int i = h[t];~i;i = ne[i]) {
int j = e[i];
if (!dp[j]) dp[j] = dp[t] + 1;
q.push (j);
}
}
}
int main()
{
cin >> n;
memset (h, -1, sizeof h);
for (int i = 1;i <= n;i ++) {
int j;
cin >> j;
if (j != -1) add (j, i);
else rt = i;
}
bfs (rt);
cout << mx << endl;
int i = 1;
while (dp[i] != mx) i ++;
cout << i;
i ++;
for (;i <= n;i ++)
if (dp[i] == mx)
cout << ' ' << i;
return 0;
}
L2-027 名人堂与代金券 (25 分)
美观一点的话还可以使用pair。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n, G, k, money, r[N];
struct student {
string em;
int sc;
} stu[N];
bool cmp (student a, student b) {
if (a.sc != b.sc) return a.sc > b.sc;
return a.em < b.em;
}
int main()
{
cin >> n >> G >> k;
for (int i = 1;i <= n;i ++) {
cin >> stu[i].em >> stu[i].sc;
if (stu[i].sc >= G) money += 50;
else if (stu[i].sc >= 60) money += 20;
}
sort (stu+1, stu+n+1, cmp);
cout << money << endl;
for (int i = 1;i <= n;i ++) {
if (stu[i].sc != stu[i-1].sc) r[i] = i;
else r[i] = r[i-1];
if (r[i] <= k)
cout << r[i] << ' ' << stu[i].em << ' ' << stu[i].sc << endl;
}
return 0;
}
L2-028 秀恩爱分得快 (25 分)
坑太深:
- 存在-0和0的情况,用int控制输入是不行的。
- 超时要用scanf。
#include<bits/stdc++.h>
using namespace std;
const int N = 1100;
int n, T, k;
string x, y;
int a[N];
int st[N];
double e[N][N];
double find (int x) {
double res = -1;
for (int i = 0;i < n;i ++) {
if (st[x] ^ st[i])
res = max (res, e[x][i]);
}
return res;
}
int main()
{
cin >> n >> T;
while (T --) {
scanf ("%d", &k);
for (int i = 0;i < k;i ++) {
cin >> x;
a[i] = atoi (x.substr(x[0] == '-').c_str());
st[a[i]] = (x[0] != '-');
for (int j = 0;j < i;j ++)
if (st[a[i]] ^ st[a[j]]) {
e[a[i]][a[j]] += 1.0 / k;
e[a[j]][a[i]] += 1.0 / k;
}
}
}
cin >> x >> y;
int xx = atoi (x.substr(x[0] == '-').c_str());
int yy = atoi (y.substr(y[0] == '-').c_str());
double mx1 = find (xx);
double mx2 = find (yy);
if (mx1 == e[xx][yy] && mx2 == e[xx][yy]) {
cout << x << ' ' << y << endl;
} else {
for (int i = 0;i < n;i ++)
if (st[xx] ^ st[i] && e[xx][i] == mx1)
cout << x << ' ' << (st[i]==0?"-":"") << i << endl;
for (int i = 0;i < n;i ++)
if (st[yy] ^ st[i] && e[yy][i] == mx2)
cout << y << ' ' << (st[i]==0?"-":"") << i << endl;
}
return 0;
}
L2-029 特立独行的幸福 (25 分)
L2-030 冰岛人 (25 分)
L2-031 深入虎穴 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, st[N], dis[N];
int e[N<<1], ne[N<<1], h[N], idx;
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void bfs (int x) {
int ans = 0;
queue <int> q;
q.push (x);
while (q.size()) {
int t = q.front ();
q.pop ();
ans = t;
for (int i = h[t];~i;i = ne[i]) {
int j = e[i];
q.push (j);
}
}
cout << ans << endl;
}
int main()
{
cin >> n;
memset (h, -1, sizeof h);
for (int i = 1;i <= n;i ++) {
int k;
cin >> k;
while (k --) {
int b;
cin >> b;
add (i, b);
st[b] = 1;
}
}
int entry;
for (int i = 1;i <= n;i ++)
if (!st[i]) entry = i;
bfs (entry);
return 0;
}
L2-032 彩虹瓶 (25 分)
吐了,注释地方直接break导致当前行还没输入完,把当前行剩下的货物当作下一次的输入了……debug好久。
而且最可怕的是错的是第一个测试点,第一个测试点15分……
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, m, k;
stack <int> s;
int main()
{
cin >> n >> m >> k;
while (k --) {
int task = 1, id, flag = 0;
while (s.size ()) s.pop ();
for (int i = 1;i <= n;i ++) {
cin >> id;
if (id != task) {
s.push (id);
if (s.size () > m)
flag = 1; // 不能break啊!!!
} else {
task ++;
while (s.size() && s.top() == task) {
s.pop ();
task ++;
}
}
}
if (task > n && !flag) puts ("YES");
else puts ("NO");
}
return 0;
}
L2-033 简单计算器 (25 分)
太简单了吧(感动)
注意是 n 2 o p n 1 n_2\space op\space n_1 n2 op n1。
#include<bits/stdc++.h>
using namespace std;
int n, num;
char op;
stack <int> s1;
stack <char> s2;
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> num, s1.push (num);
for (int i = 1;i < n;i ++) cin >> op, s2.push (op);
while (s1.size() && s2.size()) {
int a = s1.top (); s1.pop ();
int b = s1.top (); s1.pop ();
char op = s2.top (); s2.pop ();
int ans;
if (op == '+') ans = b + a;
else if (op == '-') ans = b - a;
else if (op == '*') ans = b * a;
else if (a == 0) {
printf ("ERROR: %d/0", b);
return 0;
} else {
ans = b / a;
}
if (s1.empty () && s2.empty ()) cout << ans << endl;
else s1.push (ans);
}
return 0;
}
L2-034 口罩发放 (25 分)
狗都不做!什么屁题,仨小时没过。
L2-035 完全二叉树的层序遍历 (25 分)
利用完全二叉树索引的性质操作实现太棒了!
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int n, tree[N];
void build (int x) { // 根节点的索引值
if (x > n) return ;
build (x << 1); // 左子树根节点的索引值
build (x << 1 | 1); // 右子树根节点的索引值
cin >> tree[x]; // 先递归遍历左子树和右子树,再到达根节点,输入根节点
}
int main()
{
cin >> n;
build (1);
cout << tree[1];
for (int i = 2;i <= n;i ++) // 以索引方式保存的二叉树按索引顺序遍历就是层序遍历
cout << ' ' << tree[i];
return 0;
}
L2-036 网红点打卡攻略 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 300, INF = 0x3f3f3f3f;
int n;
int e[N][N], st[N], a[N], min_cost = INF, min_cost_id;
vector <int> v;
int cost (int m) {
int s = 0, res = 0;
a[m+1] = 0;
memset (st, 0, sizeof st);
for (int i = 0;i <= m;i ++) {
int tmp = e[a[i]][a[i+1]];
if (tmp == INF || st[a[i]]) return -1;
res += tmp;
st[a[i]] = 1;
}
for (int i = 1;i <= n;i ++)
if (!st[i]) return -1;
return res;
}
int main()
{
memset (e, 0x3f, sizeof e);
int k, m;
cin >> n >> m;
while (m --) {
int a, b, c;
cin >> a >> b >> c;
e[a][b] = e[b][a] = c;
}
cin >> k;
for (int i = 1;i <= k;i ++) {
cin >> m;
for (int j = 1;j <= m;j ++) cin >> a[j];
int cur_cost = cost(m);
if (cur_cost != -1) {
v.push_back (i);
if (min_cost > cur_cost)
min_cost_id = i,
min_cost = cur_cost;
}
}
cout << v.size() << endl << min_cost_id << ' ' << min_cost;
return 0;
}
L2-037 包装机 (25 分)
又是在debug。
注意:
- 当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落
- 如果轨道已经空了,再按对应的按钮不会发生任何事(就连如果框满了,也不会强制抓物品)
搁这考语文呢!
#include<bits/stdc++.h>
using namespace std;
string ans = "";
string goods[110];
stack <char> s;
int main()
{
int n, m, mx, op;
cin >> n >> m >> mx;
for (int i = 1;i <= n;i ++)
cin >> goods[i];
while (1) {
cin >> op;
if (op == -1) break;
if (op == 0) {
if (s.size ())
ans += s.top (),
s.pop ();
} else if (op >= 1 && op <= n){
if (goods[op].size ()) {
if (s.size () == mx) {
ans += s.top ();
s.pop ();
}
s.push (goods[op][0]),
goods[op].erase (0, 1);
}
}
}
cout << ans << endl;
return 0;
}
L2-038 病毒溯源 (25 分)
再次注意记录最大路径长度时要在for外面!
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, rt, mx_dis;
int fa[N], dis[N], st[N];
int e[N<<1], ne[N<<1], h[N], idx;
vector <int> v[N];
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void path (int x, int cnt) {
if (x == -1) return ;
path(fa[x], cnt);
v[cnt].push_back (x);
}
void bfs (int x) {
queue<int> q;
dis[x] = 1;
q.push (x);
while (q.size()) {
int t = q.front ();
q.pop ();
mx_dis = max (mx_dis, dis[t]); // 尽量不要放在for里面,如果根节点无孩子节点,那么mx_dis就不会被赋值
for (int i = h[t];~i;i = ne[i]) {
int j = e[i];
dis[j] = dis[t] + 1;
q.push (j);
fa[j] = t;
}
}
}
int main()
{
memset (fa, -1, sizeof fa);
memset (h, -1, sizeof h);
cin >> n;
for (int i = 0;i < n;i ++) {
int k;
cin >> k;
while (k --) {
int b;
cin >> b;
add (i, b);
st[b] = 1;
}
}
for (int i = 0;i < n;i ++)
if (!st[i]) rt = i;
bfs (rt);
int cnt = 0;
for (int i = 0;i < n;i ++)
if (dis[i] == mx_dis)
path (i, cnt ++);
sort (v, v + cnt); // 本质是对数组进行排序,数组的元素是vector,使用vector自带的比较函数比较大小,自带的比较函数就是题目要求的
cout << mx_dis << endl;
cout << v[0][0];
for (int i = 1;i < v[0].size();i ++)
cout << ' ' << v[0][i];
return 0;
}
L2-039 清点代码库 (25 分)
L2-040 哲哲打游戏 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, m, k, t;
int save[N];
vector <int> plot_selection[N]; // 由于第一维为1e5,第二维只给出了全部和不超过1e6,直接开太大,所以要用vector
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++) {
cin >> k;
for (int j = 1;j <= k;j ++)
cin >> t, plot_selection[i].push_back (t);
}
int cur_plot = 1;
while (m --) {
int op, j;
cin >> op >> j;
if (op == 0) {
cur_plot = plot_selection[cur_plot][j-1]; // vector从索引0开始加入,所以要j-1
} else if (op == 1){
save[j] = cur_plot;
cout << cur_plot << endl;
} else {
cur_plot = save[j];
}
}
cout << cur_plot << endl;
return 0;
}