天梯赛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;
}
posted @ 2026-04-19 14:27  dbg_8  阅读(93)  评论(0)    收藏  举报