天梯赛2026 题解
赛时代码,没给的都是用 python 写的。
3-1 之前用了 80 多分钟,后面两个不会正解,暴力拿了 16+10。总分 256,国一线 252,还有个团队国一。分数都挺集中的。
赛时居然可以看排名,我结束了才知道。
1-5
set + map 操作即可。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <set>
#define ll long long
int n, a[10003], b[10003];
std:: map < int, int > ma;
std:: set < int > se;
inline void kagari () {
std:: cin >> n;
for (int i = 1; i <= n; ++i) {
std:: cin >> a[i] >> b[i];
if (se.find(a[i]) == se.end()) se.insert(a[i]);
if (b[i] == 1) ma[a[i]] = 1;
}
std:: vector < int > v;
for (auto &i: se) if (ma.find(i) == ma.end()) v.push_back(i);
if (v.size() == 0) puts("NONE");
else {
for (int i = 0; i < v.size(); ++i) std:: cout << v[i] << (i == v.size() - 1 ? '\n' : ' ');
}
return;
}
int main () {
kagari();
return 0;
}
1-6
用 python 打得更快。
ans = ''
for i in range(11):
s = input()
ans = ans + chr(ord('0') + len(s))
print(ans)
1-7
依照题意即可。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#define ll long long
int n, a[1003], sum, ma, mi;
inline void kagari () {
std:: cin >> n;
for (int i = 1; i <= n; ++i) std:: cin >> a[i], sum += a[i];
ma = mi = a[1];
for (int i = 1; i <= n; ++i) {
if (a[i] > ma) ma = a[i];
if (a[i] < mi) mi = a[i];
}
int md = (sum / n);
printf("%d %d %d\n", ma, mi, md);
std:: vector < int > v;
for (int i = 1; i <= n; ++i) if (a[i] > md * 2) {
v.push_back(i);
}
if (v.size() == 0) puts("Normal");
else {
for (int i = 0; i < v.size(); ++i) std:: cout << v[i] << (i == v.size() - 1 ? '\n' : ' ');
}
return;
}
int main () {
kagari();
return 0;
}
1-8
和 2025 年的字符串题没什么区别,不方便用 python 和 STL 的话就纯手打,很快就能敲完。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#define ll long long
int t, n;
std:: string s, w;
inline void kagari () {
std:: cin >> t >> s;
while (t--) {
int op; std:: cin >> op;
if (op == 1) {
std:: vector < int > v;
std:: string p; std:: cin >> p;
for (int i = 0; i + p.size() - 1 < s.size(); ++i) {
bool flag = 1;
for (int j = 0; j < p.size(); ++j) if (s[i + j] != p[j]) {
flag = 0; break;
}
if (flag) v.push_back(i);
if (v.size() >= 3) break;
}
if (v.size() == 0) puts("-1");
else {
for (int i = 0; i < v.size(); ++i) std:: cout << v[i] << (i == v.size() - 1 ? '\n' : ' ');
}
}
else if (op == 2) {
int x; std:: string y; std:: cin >> x >> y;
w = "";
for (int i = 0; i < x; ++i) w.push_back(s[i]);
for (auto &i: y) w.push_back(i);
for (int i = x; i < s.size(); ++i) w.push_back(s[i]);
s = w;
std:: cout << s << '\n';
}
else {
int l, r; std:: cin >> l >> r;
w = "";
for (int i = 0; i < l; ++i) w.push_back(s[i]);
for (int i = r; i >= l; --i) w.push_back(s[i]);
for (int i = r + 1; i < s.size(); ++i) w.push_back(s[i]);
s = w;
std:: cout << s << '\n';
}
}
return;
}
int main () {
kagari();
return 0;
}
2-1
建 stack 太麻烦。注意到批改顺序要么是正着的,要么是反着的,直接 \(O(N^2)\) 暴力即可。
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stack>
#define ll long long
int n, t, a[200003];
inline void kagari () {
scanf("%d %d", &n, &t);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
std:: vector < int > ans;
int k = 1;
while (1) {
int p = 0, s = 0;
if (k & 1) {
for (int i = 1; i <= n; ++i)
if (a[i] > t) s += a[i], ++p;
else if (a[i] != -1) ans.push_back(i), a[i] = -1;
}
else {
for (int i = n; i; --i)
if (a[i] > t) s += a[i], ++p;
else if (a[i] != -1) ans.push_back(i), a[i] = -1;
}
k++;
if (p == 0) break;
t = (int)(s / p);
}
for (int i = 0; i < n; ++i) printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
return;
}
int main () {
kagari();
return 0;
}
2-2
二分。当然,使用 lower_bound 会简单不少。
二分没打等号, wa 了一个点,查了三分钟。
#include <stdio.h>
#include <algorithm>
#include <vector>
#define ll long long
int n, a[200003];
struct NODE {
int x, y;
bool operator < (const NODE &rhs) const { return x == rhs.x ? y < rhs.y : x < rhs.x; }
} b[100003];
inline void kagari () {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), b[i].x = a[i], b[i].y = i;
std:: vector < int > ans1;
int m1 = 0;
for (int i = 1; i <= n; ++i) if (a[i] > m1) m1 = a[i];
for (int i = 1; i <= n; ++i) if (a[i] == m1) ans1.push_back(i);
for (int i = 0; i < ans1.size(); ++i) printf("%d%c", ans1[i], i == ans1.size() - 1 ? '\n' : ' ');
int q; scanf("%d", &q);
std:: sort(b + 1, b + n + 1);
while (q--) {
int p; scanf("%d", &p);
int l = 1, r = n;
NODE nd = {p, 100000001};
while (l <= r) {
int mid = l + r >> 1;
// printf("find %d\n", b[mid].x);
if (nd < b[mid]) r = mid - 1;
else l = mid + 1;
}
// l++;
// printf("## %d %d\n", l, b[l].x);
if (l < 1 || l > n || b[l].x <= p) puts("0");
else printf("%d\n", b[l].y);
}
return;
}
int main () {
kagari();
return 0;
}
2-3
两遍 dfs,第一遍求最大值,第二遍求答案。
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stack>
#define ll long long
struct NODE{
int y, z;
};
int n, m, d[100003];
std:: vector < NODE > g[100003];
std:: vector < int > v;
int ans = 0;
void dfs1 (int i, int s) {
if (g[i].empty()) {
if (s > ans) ans = s;
return;
}
for (auto &j: g[i]) dfs1(j.y, std:: min(s, j.z));
}
void dfs2 (int i, int s) {
if (g[i].empty()) {
if (s == ans) v.push_back(i);
return;
}
for (auto &j: g[i]) dfs2(j.y, std:: min(s, j.z));
}
inline void kagari () {
scanf("%d", &n);
for (int i = 1; i < n; ++i) {
int y, z; scanf("%d %d", &y, &z);
g[y].push_back({i, z});
}
dfs1(0, 10000);
dfs2(0, 10000);
printf("%d\n", ans);
std:: sort(v.begin(), v.end());
for (int i = 0; i < v.size(); ++i) printf("%d%c", v[i], (i == v.size() - 1 ? '\n' : ' '));
return;
}
int main () {
kagari();
return 0;
}
2-4
与上题类似。
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stack>
#define ll long long
struct NODE{
int y, z;
};
int n, m, d[10003];
std:: vector < NODE > g[10003];
std:: vector < int > v;
inline void print() {
}
void dfs (int i) {
v.push_back(i);
d[i] = 1;
if (g[i].size() == 0) return;
auto p = g[i][0];
for (auto &j: g[i]) if (!d[j.y]) p = j;
for (auto &j: g[i]) if (!d[j.y] && (j.z == p.z ? j.y < p.y : j.z > p.z)) p = j;
if (!d[p.y]) dfs(p.y);
}
inline void kagari () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
int x, y, z; scanf("%d %d %d", &x, &y, &z);
g[x].push_back({y, z});
}
int q; scanf("%d", &q);
while (q--) {
int x; scanf("%d", &x);
v.clear();
for (int i = 1; i <= n; ++i) d[i] = 0;
dfs(x);
for (int i = 0; i < v.size(); ++i) printf("%d%s", v[i], (i == v.size() - 1 ? "\n" : "->"));
}
return;
}
int main () {
kagari();
return 0;
}
3-1
\(O(n^2)\) 枚举即可,实际上跑不满。当然可以开一个优先队列,加上特判,优化成 \(O(n\log n)\) 级别的,但没必要。
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#define ll long long
int n;
struct NODE {
int x, y, z;
std:: string id;
} a[10003];
std:: vector < int > ans;
inline void kagari () {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) std:: cin >> a[i].x >> a[i].y >> a[i].id >> a[i].z, a[i].z = (a[i].z >= 80 ? 1 : 0);
for (int ti = 1; ti <= n * 2; ++ti) {
int t = 0;
for (int i = 1; i <= n; ++i) if (a[i].z != -1) {
if (a[i].x <= ti) {
if (t == 0) t = i;
if (a[i].y == ti) {
t = i; break;
}
else if (a[i].z == 1 && (a[i].y < a[t].y && a[t].z == 1 || a[t].z == 0)) {
t = i;
}
else if (a[t].z != 1 && a[i].y < a[t].y)
t = i;
}
else break;
}
if (!t) continue;
ans.push_back(t);
a[t].z = -1, a[t].x = ti;
}
for (int i = 0; i < n; ++i) std:: cout << a[ans[i]].x << ' ' << a[ans[i]].id << '\n';
return;
}
int main () {
kagari();
return 0;
}
3-2
如下贪心乱搞可以 16 分。这个 dfs 是推答案用的。
正解貌似是二分图网络流,想到了一点,不会。
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stack>
#define ll long long
int n, a[100003], b[100003], c[100003], d[100003];
int ans;
void dfs (int cur) {
if (cur > n) {
int res = n * 2;
std:: vector < int > p, q;
for (int i = 1; i <= n; ++i)
if (d[i])
p.push_back(a[i]);
else
q.push_back(b[i]);
std:: sort(p.begin(), p.end());
std:: sort(q.begin(), q.end());
for (int i = 1; i < p.size(); ++i) if (p[i] == p[i - 1]) --res;
for (int i = 1; i < q.size(); ++i) if (q[i] == q[i - 1]) --res;
ans = std:: min(ans, res);
return;
}
d[cur] = 0;
dfs(cur + 1);
d[cur] = 1;
dfs(cur + 1);
}
inline void kagari () {
ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) c[i] = d[i] = 0;
for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i], &b[i]), c[a[i]]++, d[b[i]]++;
if (0) {
ans = n * 2;
dfs(1);
printf("%d\n", ans);
return;
}
for (int i = 1; i <= n; ++i) if (c[i]) --c[i];
for (int i = 1; i <= n; ++i) if (d[i]) --d[i];
// for (int i = 1; i <= n; ++i) printf("\t%d %d\n", c[i], d[i]);
for (int i = 1; i <= n; ++i)
if (c[a[i]] && d[b[i]]) {
--c[a[i]];
}
for (int i = 1; i <= n; ++i) ans += c[i] + d[i];
printf("%d\n", n * 2 - ans);
return;
}
int main () {
int t; scanf("%d", &t);
while (t--) kagari();
return 0;
}
3-3
推不出来。dfs 暴力 10 分。后面一大串是假的 \(O(n^2)\) 做法。
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stack>
#define MODN 998244353ll
#define ll long long
int n, a[100003], b[100003];
ll ans = 0;
void dfs (int cur) {
if (cur > n) {
for (int i = 1; i <= n; ++i) if (a[b[i]] != b[a[i]]) return;
// for (int i = 1; i <= n; ++i) printf("%d ", b[i]); puts("");
++ans;
return;
}
for (int i = 1; i <= n; ++i) b[cur] = i, dfs(cur + 1);
}
inline void kagari () {
ans = 1;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
if (n <= 0) {
ans = 0;
dfs(1);
printf("%d\n", ans);
return;
}
for (int i = 1; i <= n; ++i) b[i] = 0;
for (int i = 1; i <= n; ++i) if (!b[i]) {
ll res = 0;
for (int j = 1; j <= n; ++j) if (b[j] > 0) b[j] = -b[j];
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= n; ++k) if (b[k] > 0) b[k] = 0;
b[i] = j;
int len = 0, k = i;
bool flag = 1;
while (1) {
// printf("# %d %d\n", k, b[k]);
// for (int i = 1; i <= n; ++i) printf("%d ", b[i]); puts("");
++len;
// b[a[k]] = a[b[k]]
if (b[a[k]] > 0 && b[a[k]] != a[b[k]]) {
flag = 0;
break;
}
else if (b[a[k]] > 0) break;
b[a[k]] = a[b[k]];
k = a[k];
if (k == i) break;
}
if (flag) ++res;
}
// printf("~%d %d\n", i, res);
ans = ans * res % MODN;
}
printf("%lld\n", ans * n % MODN);
return;
}
int main () {
int t; scanf("%d", &t);
while (t--) kagari();
return 0;
}
( ゚∀゚)o彡゜ ヒーコー ヒーコー!

浙公网安备 33010602011771号