加几道 L1 稍微难点的。
L1-009 N个数求和
题目链接
题意:n 个分数求和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n;
int gcd(int x, int y) {
return y ? gcd(y, x % y) : x;
}
int main()
{
scanf("%d", &n);
int a, b;
int c = 0, d = 1;
for (int i = 1; i <= n; ++i) {
scanf("%d/%d", &a, &b);
c = a * d + b * c;
d = b * d;
int g = abs(gcd(c, d));
c /= g;
d /= g;
}
if (c < 0) {
putchar('-');
c = -c;
}
if (c / d || !c) printf("%d", c / d);
if (c > d && c % d) putchar(' ');
if (c % d) printf("%d/%d\n", c % d, d);
return 0;
}
|
L1-064 估值一亿的AI核心代码
题目链接
题意:根据题意修改字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <sstream>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
string s;
int main()
{
int t;
scanf("%d", &t);
getchar();
while (t--) {
getline(cin, s);
cout << s;
printf("\nAI:");
for (int i = 0; i < (int)s.size(); ++i) {
if (isupper(s[i]) && s[i] != 'I') s[i] = tolower(s[i]);
else if (!isalnum(s[i])) s.insert(i++, " ");
if (s[i] == '?') s[i] = '!';
}
stringstream ss(s);
string str[1005];
int cnt = 0;
while (ss >> s) str[cnt++] = s;
if (!isalnum(str[0][0])) printf(" ");
for (int i = 0; i < cnt; ++i) {
if (!isalnum(str[i][0])) cout << str[i];
else if ((str[i] == "can" || str[i] == "could") && str[i+1] == "you") cout << " I " << str[i++];
else if (str[i] == "I" || str[i] == "me") cout << " you";
else cout << " " << str[i];
}
puts("");
}
return 0;
}
|
L2-001 紧急救援
题目链接
题意:$n(2\le n\le500)$ 个城市编号 $0\sim$,m 条道路,出发地 s,目的地 e,每个城市都有一定的救援队数目,求最短路径条数及召集的最多的救援队数量并输出 s 到 e 的路径中经过的城市编号。
num[i]
和 w[i]
分别表示出发点到结点 i 最短路径条数,召集的最多的救援队数目,pre[i]
表示最短路径结点 i 的前一个结点。最后修改一下松弛方程即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f, N = 505, M = 3e5;
int n, m, s, e, tot;
int pre[N], num[N], weight[N], head[N];
int d[N], w[N], vis[N];
int ver[M], edge[M], nxt[M];
void add(int x, int y, int z) {
ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot;
}
void dijkstra() {
priority_queue<P, vector<P>, greater<P> > q;
memset(vis, 0, sizeof(vis));
memset(d, 0x3f, sizeof(d));
d[s] = 0;
num[s] = 1;
w[s] = weight[s];
q.push(P(0, s));
while (!q.empty()) {
int x = q.top().second;
q.pop();
if (vis[x]) continue;
vis[x] = 1;
for (int i = head[x]; i; i = nxt[i]) {
int y = ver[i];
if (d[y] > d[x] + edge[i]) {
d[y] = d[x] + edge[i];
num[y] = num[x];
w[y] = w[x] + weight[y];
pre[y] = x;
q.push(P(d[y], y));
}
else if (d[y] == d[x] + edge[i]) {
num[y] += num[x];
if (w[y] < w[x] + weight[y]) {
w[y] = w[x] + weight[y];
pre[y] = x;
}
}
}
}
}
void print(int x) {
if (x == s) {
printf("%d", x);
return;
}
print(pre[x]);
printf(" %d", x);
}
int main()
{
scanf("%d%d%d%d", &n, &m, &s, &e);
for (int i = 0; i < n; ++i) scanf("%d", &weight[i]);
while (m--) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
dijkstra();
printf("%d %d\n", num[e], w[e]);
print(e);
puts("");
return 0;
}
|
L2-002 链表去重
题目链接
题意:给出带整数值键值的链表 L,把绝对值重复的键值结点删除,输出去重后链表与删除的链表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
struct node {
int key, nxt;
}a[N];
int s, n;
int cnt1, cnt2;
int vis[N], ans1[N], ans2[N];
int main()
{
scanf("%d%d", &s, &n);
for (int i = 1; i <= n; ++i) {
int x;
scanf("%d", &x);
scanf("%d%d", &a[x].key, &a[x].nxt);
}
for (int i = s; ~i; i = a[i].nxt) {
int val = abs(a[i].key);
if (!vis[val]) {
vis[val] = 1;
ans1[++cnt1] = i;
}
else ans2[++cnt2] = i;
}
for (int i = 1; i <= cnt1; ++i) {
if (i == cnt1) printf("%05d %d -1\n", ans1[i], a[ans1[i]].key);
else printf("%05d %d %05d\n", ans1[i], a[ans1[i]].key, ans1[i+1]);
}
for (int i = 1; i <= cnt2; ++i) {
if (i == cnt2) printf("%05d %d -1\n", ans2[i], a[ans2[i]].key);
else printf("%05d %d %05d\n", ans2[i], a[ans2[i]].key, ans2[i+1]);
}
return 0;
}
|
L2-003 月饼
题目链接
题意:已知 n 种月饼的库存与总售价,以及市场需求量,求最大收益。
贪心,注意库存与总售价可能为小数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1005;
struct mooncake {
double amount, price, unit;
friend bool operator <(mooncake a, mooncake b) {
return a.unit > b.unit;
}
}a[N];
int n, d;
int main()
{
scanf("%d%d", &n, &d);
for (int i = 1; i <= n; ++i) scanf("%lf", &a[i].amount);
for (int i = 1; i <= n; ++i) {
scanf("%lf", &a[i].price);
a[i].unit = a[i].price / a[i].amount;
}
sort(a + 1, a + n + 1);
double ans = 0;
for (int i = 1; i <= n; ++i) {
if (a[i].amount <= d) {
ans += a[i].price;
d -= a[i].amount;
}
else {
ans += a[i].unit * d;
break;
}
}
printf("%.2lf\n", ans);
return 0;
}
|
L2-004 这是二叉搜索树吗?
题目链接
题意:给出一个长度为 n 的序列,若是二叉搜索树或镜像前序遍历的结果,输出 YES 及后序遍历结果,否则输出 NO。
假设是二叉搜索树,根据性质求出其后序遍历,长度小于 n 用镜像再试一次,长度仍然小于 n 说明不是二叉搜索树或镜像。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1005;
int n, cnt, isMirror;
int preord[N], postord[N];
void getpost(int root, int tail) {
if (root > tail) return;
int p = root + 1, q = tail;
if (!isMirror) {
while (p <= tail && preord[root] > preord[p]) p++;
while (q > root && preord[root] <= preord[q]) q--;
} else {
while (p <= tail && preord[root] <= preord[p]) p++;
while (q > root && preord[root] > preord[q]) q--;
}
if (p - q != 1) return;
getpost(root + 1, q);
getpost(p, tail);
postord[++cnt] = preord[root];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &preord[i]);
getpost(1, n);
if (cnt != n) {
isMirror = 1;
cnt = 0;
getpost(1, n);
}
if (cnt == n) {
puts("YES");
printf("%d", postord[1]);
for (int i = 2; i <= n; ++i) {
printf(" %d", postord[i]);
}
puts("");
}
else puts("NO");
return 0;
}
|
L2-005 集合相似度
题目链接
题意:两个整数集合相似度定义为:$N_c/N_t\times100%$,其中 $N_c$ 是两个集合都有的不相等整数个数,$N_t$ 是两个集合一共有的不相等整数个数,求任意一对集合的相似度。
直接用 set 存储即可不考虑重复元素,将一个集合如元素个数作为 $N_t$,遍历另一个集合每一个元素寻找前一个集合是否有该元素,有则 $N_c$++,否则 $N_t$++。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 55;
int n, m, k;
set<int> s[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &m);
int x;
for (int j = 1; j <= m; ++j) {
scanf("%d", &x);
s[i].insert(x);
}
}
scanf("%d", &k);
int a, b;
for (int i = 1; i <= k; ++i) {
scanf("%d%d", &a, &b);
int nc = 0, nt = s[b].size();
for (auto it = s[a].begin(); it != s[a].end(); ++it) {
if (s[b].find(*it) == s[b].end()) nt++;
else nc++;
}
double ans = 1.0 * nc / nt * 100;
printf("%.2lf%%\n", ans);
}
return 0;
}
|
L2-006 树的遍历
题目链接
题意:给出二叉树的后序遍历序列和中序遍历序列,输出层序遍历序列。
法一:先建树再用 bfs 输出层序遍历序列。法二:与求先序遍历类似,结点加序号对应值存在 map 中直接输出。
法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 35;
int n, tot;
int inord[N], postord[N], level[N];
int lch[N], rch[N];
int build(int l1, int r1, int l2, int r2) {
if (l1 > r1) return 0;
int rt = postord[r2];
int p = l1;
while (inord[p] != rt) p++;
int cnt = p - l1;
lch[rt] = build(l1, p - 1, l2, l2 + cnt - 1);
rch[rt] = build(p + 1, r1, l2 + cnt, r2 - 1);
return rt;
}
void LevelOrder() {
queue<int> q;
q.push(postord[n]);
while (!q.empty()) {
int x = q.front();
q.pop();
level[++tot] = x;
if (lch[x]) q.push(lch[x]);
if (rch[x]) q.push(rch[x]);
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &postord[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &inord[i]);
build(1, n, 1, n);
LevelOrder();
printf("%d", level[1]);
for (int i = 2; i <= tot; ++i) printf(" %d", level[i]);
puts("");
return 0;
}
|
法二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 35;
int n;
int inord[N], postord[N];
map<int, int> level;
void pre(int rt, int l, int r, int index) {
if (l > r) return;
int p = l;
while (p < r && inord[p] != postord[rt]) p++;
level[index] = postord[rt];
pre(rt - 1 - r + p, l, p - 1, index<<1);
pre(rt - 1, p + 1, r, index<<1|1);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &postord[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &inord[i]);
pre(n, 1, n, 1);
auto it = level.begin();
printf("%d", it->second);
while (++it != level.end()) printf(" %d", it->second);
puts("");
return 0;
}
|
L2-007 家庭房产
题目链接
题意:给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。
并查集+模拟即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1005, M = 10005;
struct person {
int id, num, area;
}a[N];
struct node {
int id, people, flag;
double avgnum, avgarea;
friend bool operator <(node a, node b) {
if (a.avgarea != b.avgarea) return a.avgarea > b.avgarea;
else return a.id < b.id;
}
}ans[M];
int n, k, cnt;
int fa[M], vis[M];
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void unite(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx > fy) fa[fx] = fy;
else if (fx < fy) fa[fy] = fx;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < M; ++i) fa[i] = i;
for (int i = 1; i <= n; ++i) {
int p1, p2;
scanf("%d%d%d%d", &a[i].id, &p1, &p2, &k);
vis[a[i].id] = 1;
if (~p1) {
vis[p1] = 1;
unite(a[i].id, p1);
}
if (~p2) {
vis[p2] = 1;
unite(a[i].id, p2);
}
for (int j = 1; j <= k; ++j) {
int x;
scanf("%d", &x);
vis[x] = 1;
unite(a[i].id, x);
}
scanf("%d%d", &a[i].num, &a[i].area);
}
for (int i = 1; i <= n; ++i) {
int id = find(a[i].id);
ans[id].id = id;
ans[id].avgnum += a[i].num;
ans[id].avgarea += a[i].area;
ans[id].flag = 1;
}
for (int i = 0; i < M; ++i) {
if (vis[i])
ans[find(i)].people++;
if (ans[i].flag)
cnt++;
}
for (int i = 0; i < M; ++i) {
if (ans[i].flag) {
ans[i].avgnum = 1.0 * ans[i].avgnum / ans[i].people;
ans[i].avgarea = 1.0 * ans[i].avgarea / ans[i].people;
}
}
sort(ans, ans + M);
printf("%d\n", cnt);
for (int i = 0; i < cnt; ++i) {
printf("%04d %d %.3lf %.3lf\n", ans[i].id, ans[i].people, ans[i].avgnum, ans[i].avgarea);
}
return 0;
}
|
L2-008 最长对称子串
题目链接
题意:求字符串的最长回文子序列。
用 gets 会编译错误,求最长回文子序列直接用 Manacher 算法,$p[i]$ 以 $s[i]$ 为中心的最长回文串半径,$maxr$ 为所有已找到回文串的最右端,中心为 $mid$,$i$ 关于 $mid$ 对称点 $2 * mid-i$,则 $p[i]=\min(p[2 * mid-i],maxr-i)$,之后再进行扩展。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 2e3 + 5;
int n, ans;
int p[N];
char s[N];
string str;
void manacher() {
s[0] = '$', s[1] = '#';
for (int i = 0; i < n; ++i) {
s[(i<<1)+2] = str[i];
s[(i<<1)+3] = '#';
}
n = (n<<1) + 2; s[n] = 0;
int maxr = 0, mid = 0;
for (int i = 1; i < n; ++i) {
if (maxr > i) p[i] = min(p[2*mid-i], maxr - i);
else p[i] = 1;
for (; s[i+p[i]] == s[i-p[i]]; ++p[i]);
if (i + p[i] > maxr) { maxr = i + p[i]; mid = i; }
}
}
int main()
{
getline(cin, str);
n = str.length();
manacher();
for (int i = 1; i < n; ++i) ans = max(ans, p[i]);
printf("%d\n", ans - 1);
return 0;
}
|
L2-009 抢红包
题目链接
题意:给出 $n$ 个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。
结构体排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
struct node {
int id, num, money;
friend bool operator <(node a, node b) {
if (a.money != b.money) return a.money > b.money;
else if (a.num != b.num) return a.num > b.num;
else return a.id < b.id;
}
}a[N];
int n, k;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
a[i].id = i;
scanf("%d", &k);
int x, y;
for (int j = 1; j <= k; ++j) {
scanf("%d%d", &x, &y);
a[i].money -= y;
a[x].money += y;
a[x].num++;
}
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i) {
printf("%d %.2lf\n", a[i].id, 1.0 * a[i].money / 100);
}
return 0;
}
|
L2-010 排座位
题目链接
题意:n 个人,m 组关系,k 组询问,每次询问 x, y 是否能被安排同席。
朋友的朋友也是朋友,为传递关系,用并查集只需合并朋友关系,敌人关系用二维数组标记即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 105;
int n, m, k;
int fa[N], r[N][N];
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void unite(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) fa[fx] = fy;
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; ++i) fa[i] = i;
int x, y, z;
while (m--) {
scanf("%d%d%d", &x, &y, &z);
if (z == 1) unite(x, y);
else r[x][y] = r[y][x] = 1;
}
for (int i = 1; i <= k; ++i) {
scanf("%d%d", &x, &y);
if (find(x) == find(y)) {
if (!r[x][y]) puts("No problem");
else puts("OK but...");
}
else {
if (!r[x][y]) puts("OK");
else puts("No way");
}
}
return 0;
}
|
L2-011 玩转二叉树
题目链接
题意:已知二叉树的中序遍历序列和前序遍历序列,求该树翻转后的层序遍历序列。
类似第 6 题,有点奇怪为啥法一 clang 会 RE 一个点。
法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 35;
int n, tot;
int preord[N], inord[N], level[N];
int lch[N], rch[N];
int build(int l1, int r1, int l2, int r2) {
if (l1 > r1 || l2 > r2) return 0;
int rt = preord[l1], p = l2;
while (inord[p] != rt) p++;
int cnt = p - l2;
lch[rt] = build(l1 + 1, l1 + cnt, l2, p - 1);
rch[rt] = build(l1 + cnt + 1, r1, p + 1, r2);
return rt;
}
void LevelOrder() {
queue<int> q;
q.push(preord[1]);
while (!q.empty()) {
int x = q.front();
q.pop();
level[++tot] = x;
if (rch[x]) q.push(rch[x]);
if (lch[x]) q.push(lch[x]);
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &inord[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &preord[i]);
build(1, n, 1, n);
LevelOrder();
printf("%d", level[1]);
for (int i = 2; i <= tot; ++i) printf(" %d", level[i]);
puts("");
return 0;
}
|
法二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 35;
int n;
int inord[N], preord[N], level[100000];
void levelorder(int rt, int l, int r, int index) {
if (l > r) return;
int p = l;
while (p < r && inord[p] != preord[rt]) p++;
level[index] = preord[rt];
levelorder(rt + 1, l, p - 1, index<<1|1);
levelorder(rt + 1 + p - l, p + 1, r, index<<1);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &inord[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &preord[i]);
levelorder(1, 1, n, 1);
int cnt = 0;
for (int i = 1; i < 100000; ++i) {
if (level[i] && cnt != n - 1) {
printf("%d ", level[i]);
cnt++;
}
else if (level[i]) {
printf("%d\n", level[i]);
break;
}
}
return 0;
}
|
L2-012 关于堆的判断
题目链接
题意:将一系列给定数字顺序插入一个初始为空的小顶堆 $H[]$。随后判断一系列相关命题是否为真。
建立一个小根堆模拟即可,边插入边向上调整。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e3 + 5;
int n, m;
int heap[N];
map<int, int> mp;
void up(int p) {
while (p > 1) {
if (heap[p] < heap[p/2]) {
swap(heap[p], heap[p/2]);
p /= 2;
}
else break;
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d", &heap[i]);
up(i);
}
for (int i = 1; i <= n; ++i) mp[heap[i]] = i;
int x, y;
string s;
for (int i = 1; i <= m; ++i) {
scanf("%d", &x);
cin >> s;
if (s[0] == 'a') {
scanf("%d", &y);
cin >> s >> s;
if (mp[x] / 2 == mp[y] / 2) puts("T");
else puts("F");
}
else {
cin >> s >> s;
if (s[0] == 'r') {
if (mp[x] == 1) puts("T");
else puts("F");
}
else if (s[0] == 'p') {
cin >> s;
scanf("%d", &y);
if (mp[x] == mp[y] / 2) puts("T");
else puts("F");
}
else {
cin >> s;
scanf("%d", &y);
if (mp[x] / 2 == mp[y]) puts("T");
else puts("F");
}
}
}
return 0;
}
|
L2-013 红色警报
题目链接
题意:n 个城市,m 条通路,k 条信息即 k 个攻占的城市,对每个被攻占的城市,如果它会改变整个国家的连通性,则输出 Red Alert: City k is lost!
,其中k是该城市的编号;否则只输出 City k is lost.
即可。。
法一:并查集,cnt 为删除某结点前连通分量个数,cur 为删除后连通分量,若个数不变 cur == cnt
或连通分量仅含该结点 cur + 1 == cnt
则不会改变整个国家连通性。法二:dfs 判断连通分量个数,cnt 为攻占前连通分量个数,cur 为攻占后连通分量个数,被攻占城市本身为一个连通分量,cur <= cnt + 1
表面未改变连通性。
法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 505, M = 5005;
struct edge {
int u, v;
}e[M];
int n, m, k;
int fa[N], vis[N];
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void unite(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) fa[fx] = fy;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i) fa[i] = i;
for (int i = 1; i <= m; ++i) {
scanf("%d%d", &e[i].u, &e[i].v);
unite(e[i].u, e[i].v);
}
int cnt = 0;
for (int i = 0; i < n; ++i) if (fa[i] == i) cnt++;
scanf("%d", &k);
int x;
for (int i = 1; i <= k; ++i) {
scanf("%d", &x);
vis[x] = 1;
for (int j = 0; j < n; ++j) fa[j] = j;
for (int j = 1; j <= m; ++j) {
if (!vis[e[j].u] && !vis[e[j].v]) unite(e[j].u, e[j].v);
}
int cur = 0;
for (int j = 0; j < n; ++j) {
if (!vis[j] && fa[j] == j) cur++;
}
if (cur + 1 == cnt || cur == cnt) printf("City %d is lost.\n", x);
else printf("Red Alert: City %d is lost!\n", x);
cnt = cur;
}
if (k == n) puts("Game Over.");
return 0;
}
|
法二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 505;
int n, m, k;
int a[N][N], vis[N];
void dfs(int x) {
vis[x] = 1;
for (int y = 0; y < n; ++y)
if (!vis[y] && a[x][y]) dfs(y);
}
int count() {
int cnt = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; ++i) {
if (!vis[i]) {
dfs(i);
cnt++;
}
}
return cnt;
}
int main()
{
scanf("%d%d", &n, &m);
int x, y;
for (int i = 1; i <= m; ++i) {
scanf("%d%d", &x, &y);
a[x][y] = a[y][x] = 1;
}
int cnt = count();
scanf("%d", &k);
for (int i = 0; i < k; ++i) {
scanf("%d", &x);
for (int y = 0; y < n; ++y) {
if (a[x][y]) {
a[x][y] = a[y][x] = 0;
}
}
int cur = count();
if (cur > cnt + 1) printf("Red Alert: City %d is lost!\n", x);
else printf("City %d is lost.\n", x);
cnt = cur;
}
if (k == n) puts("Game Over.");
return 0;
}
|
L2-014 列车调度
题目链接
题意:两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有 N 条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
实质是 LIS。对于任意一个进入的列车,如果序号大于每一个队列队尾序号,不能加入已有队列,需进入新的铁轨,否则选择第一个大于它序号的队尾序号,利用 stl set 自动排序的性质,一开始插入 0,最后答案为 s.size() - 1
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n;
set<int> s;
int main()
{
scanf("%d", &n);
s.insert(0);
int x;
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
if (x < *s.rbegin()) {
s.erase(*(s.upper_bound(x)));
}
s.insert(x);
}
printf("%d\n", (int)s.size() - 1);
return 0;
}
|
L2-015 互评成绩
题目链接
题意:n个学生,每个人的作业会被 k 个同学评审,得到 k 个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩,按非递减顺序输出最后得分最高的 m 个成绩。
纯计算题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
int n, k, m;
double a[N];
int main()
{
scanf("%d%d%d", &n, &k, &m);
int x, maxn, minn;
double s;
for (int i = 1; i <= n; ++i) {
s = 0;
maxn = 0, minn = 100;
for (int j = 1; j <= k; ++j) {
scanf("%d", &x);
s += x;
if (x > maxn) maxn = x;
if (x < minn) minn = x;
}
a[i] = 1.0 * (s - maxn - minn) / (k - 2);
}
sort(a + 1, a + n + 1);
printf("%.3lf", a[n-m+1]);
for (int i = n - m + 2; i <= n; ++i) printf(" %.3lf", a[i]);
puts("");
return 0;
}
|
L2-016 愿天下有情人都是失散多年的兄妹
题目链接
题意:两个人最近的共同祖先如果在五代以内则不可通婚,请你帮助一对有情人判断一下,他们究竟是否可以成婚?
bfs 判断是否五代以内。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
struct node {
int fa, ma, sex;
}a[N];
int n, k;
int vis[N], cnt[N];
bool bfs(int x, int y) {
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
queue<int> q;
q.push(x);
q.push(y);
cnt[x] = cnt[y] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
if (cnt[u] > 5) return 1;
if (vis[u]) return 0;
vis[u] = 1;
if (~a[u].fa && a[u].fa) {
q.push(a[u].fa);
cnt[a[u].fa] = cnt[u] + 1;
}
if (~a[u].ma && a[u].ma) {
q.push(a[u].ma);
cnt[a[u].ma] = cnt[u] + 1;
}
}
return 1;
}
int main()
{
scanf("%d", &n);
int id, fid, mid;
char c;
for (int i = 1; i <= n; ++i) {
scanf("%d %c %d %d", &id, &c, &fid, &mid);
if (c == 'M') a[id].sex = 0;
else a[id].sex = 1;
a[id].fa = fid, a[id].ma = mid;
if (~fid) a[fid].sex = 0;
if (~mid) a[mid].sex = 1;
}
scanf("%d", &k);
int x, y;
for (int i = 1; i <= k; ++i) {
scanf("%d%d", &x, &y);
if (a[x].sex == a[y].sex) puts("Never Mind");
else if (bfs(x, y)) puts("Yes");
else puts("No");
}
return 0;
}
|
L2-017 人以群分
题目链接
题意:社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。
排序取一半。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
int n, sum;
int a[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
sum += a[i];
}
sort(a + 1, a + n + 1);
int half = 0;
for (int i = 1; i <= n / 2; ++i) half += a[i];
printf("Outgoing #: %d\nIntroverted #: %d\nDiff = %d\n", n - n / 2, n / 2, sum - 2 * half);
return 0;
}
|
L2-018 多项式A除以B
题目链接
题意:多项式 Q 除 R,分别输出商和余。
模拟即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const double eps = 1e-8;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
int n, m;
double a[N], b[N], c[N];
int getnum(double c[], int expo) {
int cnt = 0;
for (int i = expo; i >= 0; --i)
if (abs(c[i]) + 0.05 >= 0.1) cnt++;
return cnt;
}
void print(double c[], int expo) {
int num = getnum(c, expo);
printf("%d", num);
if (!num) printf(" 0 0.0");
for (int i = expo; i >= 0; --i)
if (abs(c[i]) + 0.05 >= 0.1) printf(" %d %.1lf", i, c[i]);
puts("");
}
int main()
{
int x, max1 = 0, max2 = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
if (x > max1) max1 = x;
scanf("%lf", &a[x]);
}
scanf("%d", &m);
for (int i = 1; i <= m; ++i) {
scanf("%d", &x);
if (x > max2) max2 = x;
scanf("%lf", &b[x]);
}
int e1 = max1, e2 = max2;
while (e1 >= e2) {
double t = a[e1] / b[e2];
c[e1 - e2] = t;
for (int i = e1, j = e2; j >= 0; --i, --j) a[i] -= b[j] * t;
while (abs(a[e1]) < eps && e1 > 0) e1--;
}
print(c, max1 - max2);
print(a, e1);
return 0;
}
|
L2-019 悄悄关注
题目链接
题意:很水的模拟题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n, m, sum;
map<string, int> vis, people;
vector<string> ans;
int main()
{
scanf("%d", &n);
string s;
int x;
for (int i = 1; i <= n; ++i) {
cin >> s;
vis[s] = 1;
}
scanf("%d", &m);
for (int i = 1; i <= m; ++i) {
cin >> s;
scanf("%d", &x);
people[s] = x;
sum += x;
}
for (map<string, int>::iterator it = people.begin(); it != people.end(); ++it) {
if (!vis[it->first]) {
if (it->second * m > sum) ans.push_back(it->first);
}
}
if (ans.empty()) puts("Bing Mei You");
else {
sort(ans.begin(), ans.end());
for (auto it = ans.begin(); it != ans.end(); ++it)
cout << *it << '\n';
}
return 0;
}
|
L2-020 功夫传人
题目链接
题意:给出师门总人数 n,祖师爷(编号为 0)功力值 z,每传一代功夫所扣百分比值 r,以及编号为 i 的人所传的徒弟k id[1] id[2] ... id[k]
,k 为 0 表示这是一位得道者,后面跟放大倍数,求所有得道者功力总值。
从祖师爷开始 dfs 即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
vector<int> v[N];
int n;
double z, r, ans;
int vis[N];
void dfs(int id, double power) {
if (vis[id]) {
ans += power * v[id][0];
return;
}
for (int i = 0; i < (int)v[id].size(); ++i)
dfs(v[id][i], power * (1 - r / 100));
}
int main()
{
scanf("%d%lf%lf", &n, &z, &r);
int k, x;
for (int i = 0; i < n; ++i) {
scanf("%d", &k);
if (!k) {
vis[i] = 1;
scanf("%d", &x);
v[i].push_back(x);
}
else {
while (k--) {
scanf("%d", &x);
v[i].push_back(x);
}
}
}
dfs(0, z);
printf("%d\n", (int)ans);
return 0;
}
|
L2-021 点赞狂魔
题目链接
题意:很水的模拟题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 105;
struct user {
string name;
int cnt, sum;
bool operator < (const user &rhs) const {
if (cnt != rhs.cnt) return cnt > rhs.cnt;
return sum * rhs.cnt < rhs.sum * cnt;
}
}a[N];
int n, k;
set<int> s;
int main()
{
scanf("%d", &n);
string str;
int x;
for (int i = 1; i <= n; ++i) {
s.clear();
cin >> str; scanf("%d", &k);
for (int j = 1; j <= k; ++j) {
scanf("%d", &x);
s.insert(x);
}
a[i] = {str, (int)s.size(), k};
}
int num = min(n, 3);
partial_sort(a + 1, a + num + 1, a + n + 1);
cout << a[1].name;
for (int i = 2; i <= num; ++i) {
cout << " " << a[i].name;
}
for (int i = 1; i <= 3 - n; ++i)
printf(" -");
puts("");
return 0;
}
|
L2-022 重排链表
题目链接
题意:给定一个单链表 $L_1\to L_2\to\cdots\to L_n$,请编写程序将链表重新排列为 $L_n\to L_1\to L_{n-1}\to L_2\to\cdots$。
结构体按顺序存到 vector 中交替输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
struct node {
int id, dat, nxt;
}a[N];
int st, n;
vector<node> v, ans;
int main()
{
scanf("%d%d", &st, &n);
int x, y, z;
for (int i = 1; i <= n; ++i) {
scanf("%d%d%d", &x, &y, &z);
a[x] = { x, y, z };
}
for (; ~st; st = a[st].nxt) v.push_back(a[st]);
int l = 0, r = v.size() - 1;
while (1) {
ans.push_back(v[r--]);
if (l > r) break;
ans.push_back(v[l++]);
if (l > r) break;
}
for (int i = 0; i < (int)ans.size(); ++i) {
if (i != (int)ans.size() - 1)
printf("%05d %d %05d\n", ans[i].id, ans[i].dat, ans[i+1].id);
else
printf("%05d %d -1\n", ans[i].id, ans[i].dat);
}
return 0;
}
|
L2-023 图着色问题
题目链接
题意:给定无向图 G=(V,E),问可否用 K 种颜色为 V 中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 505, M = 25e4 + 5;
int n, m, k, t, tot;
int head[N], color[N], vis[N];
int ver[M], nxt[M];
set<int> s;
void add(int x, int y) {
ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= m; ++i) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
scanf("%d", &t);
while (t--) {
s.clear();
for (int i = 1; i <= n; ++i) {
scanf("%d", &color[i]);
s.insert(color[i]);
}
if ((int)s.size() != k) { puts("No"); continue; }
memset(vis, 0, sizeof(vis));
int flag = 0;
for (int x = 1; x <= n; ++x) {
vis[x] = 1;
for (int i = head[x]; i; i = nxt[i]) {
int y = ver[i];
if (vis[y]) continue;
if (color[x] == color[y]) { flag = 1; break; }
}
if (flag) break;
}
if (!flag) puts("Yes");
else puts("No");
}
return 0;
}
|
L2-024 部落
题目链接
题意:n 个圈子,输出社区总人数、不相交的圈子数,并对查询输出两人是否在同一圈子。
并查集裸题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
int n, q;
int fa[N];
set<int> s;
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void unite(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx < fy) fa[fy] = fx;
else fa[fx] = fy;
}
int main()
{
for (int i = 1; i <= N; ++i) fa[i] = i;
scanf("%d", &n);
int k, x, y;
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &k, &x);
s.insert(x);
for (int j = 2; j <= k; ++j) {
scanf("%d", &y);
s.insert(y);
unite(x, y);
}
}
int cnt = 0;
for (auto it = s.begin(); it != s.end(); ++it)
if (*it == fa[*it]) cnt++;
printf("%d %d\n", (int)s.size(), cnt);
scanf("%d", &q);
while (q--) {
scanf("%d%d", &x, &y);
printf("%c\n", find(x) == find(y) ? 'Y' : 'N');
}
return 0;
}
|
L2-025 分而治之
题目链接
题意:无向图删除一系列点后判断剩余点是否孤立。
邻接表存图并记录每个点相连点的个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
int n, m, k;
int c[N], cnt[N];
vector<int> g[N];
void check() {
for (int i = 1; i <= n; ++i) {
if (c[i] > 0) {
puts("NO");
return;
}
}
puts("YES");
}
int main()
{
scanf("%d%d", &n, &m);
int x, y;
for (int i = 1; i <= m; ++i) {
scanf("%d%d", &x, &y);
cnt[x]++;
cnt[y]++;
g[x].push_back(y);
g[y].push_back(x);
}
scanf("%d", &k);
int t;
while (k--) {
scanf("%d", &t);
for (int i = 1; i <= n; ++i) c[i] = cnt[i];
for (int i = 1; i <= t; ++i) {
scanf("%d", &x);
c[x] = 0;
for (auto j : g[x])
c[j]--;
}
check();
}
return 0;
}
|
L2-026 小字辈
题目链接
题意:输出最大深度以及该深度的节点。
随便 bfs 一下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
int n, ans;
vector<int> v[N];
int d[N];
int main()
{
scanf("%d", &n);
int x;
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
if (~x) v[x].push_back(i);
else v[0].push_back(i);
}
queue<int> q;
q.push(v[0][0]);
d[v[0][0]] = 1;
while (!q.empty()) {
int x = q.front();
q.pop();
for (auto it = v[x].begin(); it != v[x].end(); ++it) {
q.push(*it);
d[*it] = d[x] + 1;
}
ans = max(ans, d[x]);
}
printf("%d\n", ans);
int f = 0;
for (int i = 1; i <= n; ++i) {
if (d[i] == ans) {
if (f) printf(" ");
printf("%d", i);
f = 1;
}
}
puts("");
return 0;
}
|
L2-027 名人堂与代金券
题目链接
题意:很水的模拟题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
struct node {
string mail;
int score;
bool operator < (const node &rhs) const {
if (score != rhs.score) return score > rhs.score;
return mail < rhs.mail;
}
}a[N];
int n, g, k, sum;
int main()
{
scanf("%d%d%d", &n, &g, &k);
for (int i = 1; i <= n; ++i) {
cin >> a[i].mail; scanf("%d", &a[i].score);
if (a[i].score >= g) sum += 50;
else if (a[i].score >= 60) sum += 20;
}
sort(a + 1, a + n + 1);
printf("%d\n", sum);
printf("1 ");
cout << a[1].mail;
printf(" %d\n", a[1].score);
int rank = 1;
for (int i = 2; i <= n; ++i) {
if (a[i].score != a[i-1].score) {
rank = i;
if (rank > k) break;
}
printf("%d ", rank);
cout << a[i].mail;
printf(" %d\n", a[i].score);
}
return 0;
}
|
L2-028 秀恩爱分得快
题目链接
题意:n 个人(编号为 $0\sim n-1$),k 张照片,每张照片两两亲密度度为 1/k,他们间的亲密度定义为所有人亲密度之和,负号表示女性,给出一对情侣 A、B,若 A、B 彼此亲密度最高,输出他们,否则分别按序号递增输出他们亲密度最高的异性。
模拟题,注意 -0 的处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1005;
int n, m;
int sex[N];
double g[N][N];
int read() {
string str;
cin >> str;
if (str == "-0") sex[0] = 1;
int num = stoi(str);
if (num < 0) num = -num, sex[num] = 1;
return num;
}
void print(int A, int B) {
if (sex[A]) printf("-");
printf("%d ", A);
if (sex[B]) printf("-");
printf("%d\n", B);
}
int main()
{
scanf("%d%d", &n, &m);
int k, num;
while (m--) {
vector<int> gender[2];
scanf("%d", &k);
for (int i = 1; i <= k; ++i) {
num = read();
if (sex[num]) gender[1].push_back(abs(num));
else gender[0].push_back(num);
}
for (int i = 0; i < (int)gender[0].size(); ++i) {
for (int j = 0; j < (int)gender[1].size(); ++j) {
g[gender[0][i]][gender[1][j]] += 1.0 / k;
g[gender[1][j]][gender[0][i]] += 1.0 / k;
}
}
}
int A = read(), B = read();
double mx1 = 0, mx2 = 0;
for (int i = 0; i < n; ++i) {
mx1 = max(mx1, g[A][i]);
mx2 = max(mx2, g[B][i]);
}
if (mx1 == g[A][B] && mx2 == g[A][B]) {
print(A, B);
}
else {
for (int i = 0; i < n; ++i)
if (g[A][i] == mx1) print(A, i);
for (int i = 0; i < n; ++i)
if (g[B][i] == mx2) print(B, i);
}
return 0;
}
|
L2-029 特立独行的幸福
题目链接
题意:对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。1 是一个幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。例如 82、68、100 的幸福是依附于 19 的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。
模拟即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e4 + 5;
int vis[N], vis1[N], cnt[N];
void solve(int x) {
int num = x;
memset(vis1, 0, sizeof(vis1));
while (1) {
int res = 0;
while (x) {
res += (x % 10) * (x % 10);
x /= 10;
}
cnt[num]++;
if (res == 1) {
return;
}
vis[res] = 1;
if (vis1[res]) {
vis[num] = 1;
return;
}
vis1[res] = 1;
x = res;
}
}
bool isprime(int x) {
if (x <= 1) return 0;
for (int i = 2; i * i <= x; ++i) {
if (x % i == 0) return 0;
}
return 1;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
for (int i = a; i <= b; ++i) {
solve(i);
}
int flag = 0;
for (int i = a; i <= b; ++i) {
if (!vis[i]) {
flag = 1;
if (isprime(i)) cnt[i] *= 2;
printf("%d %d\n", i, cnt[i]);
}
}
if (!flag) puts("SAD");
return 0;
}
|
L2-030 冰岛人
题目链接
题意:冰岛人沿用的是维京人古老的父系姓制,孩子的姓等于父亲的名加后缀,如果是儿子就加 sson,女儿则加 sdottir。因为冰岛人口较少,为避免近亲繁衍,本地人交往前先用个 App 查一下两人祖宗若干代有无联系。本题就请你实现这个 App 的功能。
模拟,注意查询到两人都是五代以外才返回 true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
struct person {
char sex;
string fa;
};
map<string, person> mp;
int n, m;
bool check(string a, string b) {
int i = 1;
for (string fa = a; !fa.empty(); fa = mp[fa].fa, ++i) {
int j = 1;
for (string fb = b; !fb.empty(); fb = mp[fb].fa, ++j) {
if (i >= 5 && j >= 5) return 1;
else if (fa == fb) return 0;
}
}
return 1;
}
int main()
{
scanf("%d", &n);
cin.tie(0);
string a, b;
for (int i = 1; i <= n; ++i) {
cin >> a >> b;
int lenb = (int)b.size();
if (b[lenb-1] == 'n') mp[a] = { 'm', b.substr(0, lenb - 4) };
else if (b[lenb-1] == 'r') mp[a] = { 'f', b.substr(0, lenb - 7) };
else mp[a].sex = b[lenb-1];
}
scanf("%d", &m);
string af, al, bf, bl;
for (int i = 1; i <= m; ++i) {
cin >> af >> al >> bf >> bl;
if (mp.find(af) == mp.end() || mp.find(bf) == mp.end() ) puts("NA");
else if (mp[af].sex == mp[bf].sex) puts("Whatever");
else printf("%s\n", check(af, bf) ? "Yes" : "No");
}
return 0;
}
|
L2-031 深入虎穴
题目链接
题意:给出了一棵树结点之间的关系,要求找最深的叶子结点。
遍历每一个叶子结点,dfs 求最大深度即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
int n, k;
int to[N], d[N];
void dfs(int x) {
if (to[x] == 0) {
d[x] = 1;
return;
}
if (!d[to[x]]) dfs(to[x]);
d[x] = d[to[x]] + 1;
}
int main()
{
scanf("%d", &n);
int x;
for (int i = 1; i <= n; ++i) {
scanf("%d", &k);
for (int j = 1; j <= k; ++j) {
scanf("%d", &x);
to[x] = i;
}
}
int maxd = -1, id;
for (int i = 1; i <= n; ++i) {
dfs(i);
if (maxd < d[i]) { maxd = d[i]; id = i; }
}
printf("%d\n", id);
return 0;
}
|
L2-032 彩虹瓶
题目链接
题意:给出一个固定容量的栈,给出一个进栈序列,每次可以出栈或否,问能否按递增顺序出栈。
用 stack 模拟即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
#define inc(i, a, b) for (int i = a; i <= b; ++i)
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n, m, k;
stack<int> s;
int main()
{
scanf("%d%d%d", &n, &m, &k);
while (k--) {
int x;
int now = 1, flag = 1;
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
s.push(x);
while (!s.empty() && s.top() == now) {
now++;
s.pop();
}
if ((int)s.size() > m) flag = 0;
}
if (s.empty() && flag) puts("YES");
else puts("NO");
while (!s.empty()) s.pop();
}
return 0;
}
|
L2-034 口罩发放
题目链接
题意:模拟题。
难点在准确理解题意。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 3e4 + 5;
struct node {
string name, id, time;
int type, pri;
friend bool operator < (node &x, node &y) {
if (x.time == y.time) return x.pri < y.pri;
return x.time < y.time;
}
}people[N];
int d, p, t, s;
map<string, int> m1, m2;
vector<node> ans1, ans2;
bool checkid(string str) {
if (str.length() != 18) return 0;
for (int i = 0; i < 18; ++i) {
if (!isdigit(str[i])) return 0;
}
return 1;
}
int main()
{
scanf("%d%d", &d, &p);
for (int i = 1; i <= d; ++i) {
scanf("%d%d", &t, &s);
vector<node> v;
node tmp;
for (int j = 1; j <= t; ++j) {
cin >> tmp.name >> tmp.id >> tmp.type >> tmp.time;
tmp.pri = j;
if (checkid(tmp.id) && tmp.type && !m2[tmp.id]) {
m2[tmp.id] = 1; ans2.push_back(tmp);
}
v.push_back(tmp);
}
sort(v.begin(), v.end());
for (auto k : v) {
if (checkid(k.id) && s) {
if (!m1[k.id]) {
m1[k.id] = i;
ans1.push_back(k);
s--;
}
else if (i - m1[k.id] - 1 >= p) {
m1[k.id] = i;
ans1.push_back(k);
s--;
}
}
}
}
for (auto i : ans1) cout << i.name << ' ' << i.id << '\n';
for (auto i : ans2) cout << i.name << ' ' << i.id << '\n';
return 0;
}
|
L2-035 完全二叉树的层序遍历
题目链接
题意:给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历序列。
很简单,后序遍历递归建树求解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x) cout << #x << " is " << x << endl
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f, N = 65;
int n, cnt;
int postord[N], tree[N];
void build(int rt) {
if (rt > n) return;
build(rt<<1); build(rt<<1|1);
tree[rt] = postord[++cnt];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &postord[i]);
build(1);
printf("%d", tree[1]);
for (int i = 2; i <= n; ++i) {
printf(" %d", tree[i]);
}
puts("");
return 0;
}
|