📌 转载声明:
本文为原创文章,首发于个人博客 acm-phrolova.top。
遵循 CC BY-NC 4.0 版权协议。转载或引用请附上原文出处链接及本声明。
原文链接: https://acm-lycoris.cn/posts/gplt%E5%9B%A2%E4%BD%93%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%A4%A9%E6%A2%AF%E8%B5%9B2026%E9%A2%98%E8%A7%A3/
GPLT 团体程序设计天梯赛 2026 题解
title: GPLT团体程序设计天梯赛2026题解
date: 2026-04-22 20:38:10
tags: [c++, 算法, 天梯赛]
categories: [GPLT天梯赛, 2026]
📝 比赛简介
GPLT 团体程序设计天梯赛 2026 全国总决赛
每道题的讲解结构:题目 → 思路 → 代码。
📚 题目目录(点击展开 / 收起)- L1-1 一行代码
- L1-2 要刷多少题
- L1-3 就挺突然的
- L1-4 普及赛排名
- L1-5 做什么都被骂怎么办
- L1-6 钓鱼佬专用挪车电话
- L1-7 网络流量监测
- L1-8 智慧文本编辑器
- L2-1 姥姥改作业
- L2-2 超参数搜索
- L2-3 森林藏宝图
- L2-4 大语言模型的推理
L1-1 一行代码
分数:5
🔖 本题小目录题目描述
“Building the Future, One Line of Code at a Time.”
输入格式
本题没有输入。
输出格式
在一行中输出 Building the Future, One Line of Code at a Time.
输入样例
无
输出样例
Building the Future, One Line of Code at a Time.
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
本题没有任何难点,直接输出指定字符串即可。
代码 (Python)
print('Building the Future, One Line of Code at a Time.')
L1-2 要刷多少题
分数:5
🔖 本题小目录题目描述
已知每年的天梯赛有 15 道题目,全新不重复。请你算一下,一共要刷多少道真题?
输入格式
输入第一行给出一个正整数 n(≤10),为题面中所述老师提出的比赛年数。
输出格式
在一行中输出学生需要做完的题目总数
输入样例
2
输出样例
30
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
直接输出n*15
代码(c++)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
int main() {
int a;
cin >> a;
cout << a * 15 << endl;
return 0;
}
L1-3 就挺突然的
分数:10
🔖 本题小目录题目描述

本题假设人类最长寿命为 250 岁,请你编写程序判断一下墙上的标语是否合理。
输入格式
输入在一行给出 2 个不超过 5000 的正整数 A 和 B,对应的标语为“蹲厕所时突然想到,A 年出生的孩子,能活到 B 年”。
输出格式
首先在第一行输出写标语的人认为 A 年出生的孩子有多长的寿命。如果该寿命超过了人类最长寿命,在第二行中输出 jiu ting tu ran de…;如果该寿命不是正数,输出 hai sheng ma?;如果寿命在正常范围内,输出 nin tai cong ming le!
输入样例1
2026 3001
输出样例1
975
jiu ting tu ran de...
输入样例2
3001 2026
输出样例2
-975
hai sheng ma?
输入样例3
2025 2275
输出样例3
250
nin tai cong ming le!
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
计算寿命
标语说“A 年出生的孩子能活到 B 年”,那么这个人活了 B - A 年。
判断合理性
如果 B - A > 250 → 超过人类最长寿命,不合理 → 输出 jiu ting tu ran de…
如果 B - A <= 0 → 还没出生或出生即死,不合理 → 输出 hai sheng ma?
否则(1 <= 寿命 <= 250)→ 合理 → 输出 nin tai cong ming le!
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int a,b;
cin>>a>>b;
int diff=b-a;
cout<<diff<<endl;
if(diff<=0){
cout<<"hai sheng ma?"<<endl;
}else{
if(diff>250){
cout<<"jiu ting tu ran de..."<<endl;
}else{
cout<<"nin tai cong ming le!"<<endl;
}
}
return 0;
}
L1-4 普及赛排名
分数:10
🔖 本题小目录题目描述
输入格式
输入第一行给出正整数 n(n<=10^4),为参赛学生人数。随后 n 行,每行给出一位参赛学生所属高校的评级分,为区间 [0,3000] 内的整数。
输出格式
在一行中输出高校评级分不低于 1700 分的高校学生总人数。
输入样例
5
1500
2700
1700
1000
1699
输出样例
3
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
定义一个计数器,小于1700就+1
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
int res=0;
while(n--){
int x;
cin>>x;
if(x<1700){
res++;
}
}
cout<<res<<endl;
return 0;
}
L1-5 做什么都被骂怎么办
分数:15
🔖 本题小目录题目描述
子曰:“那就意味着你什么都可以做。”
给定一系列人被夸或被骂的记录找出那些什么都可以做的人。
输入格式
输入第一行给出一个正整数 n(n<=10^4),是记录的条数。随后 n 行,每行按下列格式给出一个人的记录:
编号 记录
其中 编号 是 1 到 100000 的整数,记录 是 0 表示被骂,1 表示被夸。
输出格式
在一行中按升序输出那些什么都可以做(即做什么都被骂)的人的编号。数字间以 1 个空格分隔,行首尾不得有多余空格。
如果不存在这样的人,输出 NONE。
输入样例1
7
23333 0
1 0
2 0
1 1
2 0
666 1
5555 0
输出样例1
2 5555 23333
输入样例2
3
1 1
2 0
2 1
输出样例2
NONE
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
用一个字典(或哈希表)记录每个编号是否出现过“被夸”的记录。
初始时,所有编号都默认为“-1”。表示没出现
出现了就先令其为0,再加上编号值
最终只要是0就表示什么都可以做,加入答案数组即可,答案数组为空就表示NONE
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
vector<int> arr(114514,-1);
for(int i=0;i<n;i++)
{
int a,b;
cin>>a>>b;
if(arr[a]==-1){
arr[a]=0;
arr[a]+=b;
}else{
arr[a]+=b;
}
}
bool Can=false;
vector<int> res;
for(int i=0;i<114514;i++){
if(arr[i]==-1)continue;
if(arr[i]==0){
res.push_back(i);
}
}
if(res.empty()){
cout<<"NONE"<<endl;
return 0;
}else{
int cnt=res.size();
for(int i=0;i<cnt;i++){
if(i)cout<<" ";
cout<<res[i];
}cout<<endl;
}
return 0;
}
L1-6 钓鱼佬专用挪车电话
分数:15
🔖 本题小目录题目描述

本题请你判断钓鱼佬的挪车电话到底是什么?
注: 请不要拨打这个电话号码
输入格式
输入分 11 行,每行对应 11 位手机号码的一位数字,给出由 m 组成的字符串,以回车结束。每个 m 代表鱼漂上的一目,一行中有多少 m 就表示这一位数字是多少,空行代表 0。题目保证每行都不超过 9 个 m。
输出格式
一行输出钓鱼佬的手机号
输入样例
m
mm
mmmmmmmm
mmm
m
mm
m
mmmmmmmm
mmmmmmmm
mm
输出样例
12831218082
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
本题难点在于对空行的处理,很多人会直接cin,然后WA一次
注:很多人绝对不包括我(
使用getline处理空行,getline会把换行符\n读进去,如果本行只有一个换行符就取0即可
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
vector<int> res;
for(int i=0;i<11;i++){
string s;
getline(cin,s);
if(s=="\n"){
res.push_back(0);
}else{
res.push_back(s.length());
}
}
for(int i=0;i<11;i++){
cout<<res[i];
}cout<<endl;
return 0;
}
L1-7 网络流量监测
分数:20
🔖 本题小目录题目描述
编写程序,分析给定时间段内的网络流量数据,找出流量最大值、最小值、平均值和中值,并且标出超过平均值 2 倍的疑似攻击点。
输入格式
输入第一行给出正整数 n(≤10^3),为流量数据的总条数。第二行给出 n 个不超过 10^6 的非负整数,依次对应每小时记录的进入流量(以 MB 为单位)。
输出格式
输出第一行依次给出流量的最大值、最小值、平均值(向下取整。第二行升序输出所有疑似攻击点的小时数(从 1 到 n)。如果没有疑似攻击点,则输出 Normal。
同行数据间以 1 个空格分隔,行首尾不得有多余空格。
输入样例1
10
150 180 200 120 5000 136 115 131 4700 239
输出样例1
5000 115 1097
5 9
输入样例2
10
150 180 200 120 50 136 115 131 47 239
输出样例2
239 47 136
Normal
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
题目很明白了
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
vector<int> arr(n);
int Sum=0;
for(int i=0;i<n;i++){
cin>>arr[i];
Sum+=arr[i];
}
cout<<*max_element(arr.begin(),arr.end())<<" ";
cout<<*min_element(arr.begin(),arr.end())<<" ";
cout<<Sum/n<<endl;
int dan=Sum/n*2;
vector<int> res;
for(int i=0;i<n;i++){
if(arr[i]>dan){
res.push_back(i+1);
}
}
if(res.empty()){
cout<<"Normal"<<endl;
return 0;
}else{
for(int i=0;i<res.size();i++){
if(i)cout<<" ";
cout<<res[i];
}cout<<endl;
}
return 0;
}
L1-8 智慧文本编辑器
分数:20
🔖 本题小目录题目描述
为了响应潮流,龙龙打算也做一个智慧文本编辑器,但因为大语言模型的 API 太贵了,龙龙打算让这个编辑器的“智慧”停留在名字上就好了。但功能还是得写的,具体来说,对于当前正在编辑的文档,这个编辑器应当支持以下三个功能:
1 查找指定字符串 s1 前 3 次出现的位置;
2 在指定位置 p 插入一个指定字符串 s2
3 将某一段连续的字符串翻转。
真的文本编辑器可太复杂了,这里我们只简单化考虑由大小写英文字母和数字组成的字符串。
输入格式
输入第一行是一个整数 N (1≤N≤50),表示操作的数量。
第二行是一个字符串 S (1≤∣S∣≤10^3),表示待操作的初始字符串。
接下来的 N 行,每行给出一条操作指令。根据操作种类,分别为以下格式:
1 s1:对应查找操作,查找字符串 s1在当前字符串 T 中前 3 次出现的位置。
2 p s2:对应插入操作,将字符串 s2插入到当前字符串 T 中“下标为 p 的字符”之前。当 p=∣T∣ 时,表示插入到字符串末尾。
3 l r:对应翻转操作,将当前字符串 T 中下标从 l 到 r 的连续子串翻转。
字符串下标从 10 开始。保证所有输入中的字符串都只包含大小写英文字母和数字,且满足:1≤∣s1∣≤5,1≤∣s2∣≤10。
对于第二类和第三类操作,保证输入下标合法,即第二类操作满足 0≤p≤∣T∣,第三类操作满足 0≤l≤r<∣T∣。
说明:对于任意字符串 X,∣X∣ 表示字符串 X 的长度。
输出格式
对于第一类操作,按从小到大的顺序输出查找到的所有位置(即目标字符串的第一个字符在当前字符串中的下标),相邻两个位置之间用 1 个空格分隔。如果不足 3 次,就按实际查找到的次数输出;如果一次也没有找到,输出 -1。
注意:只要位置不同,就算是不同次出现,出现的字符串允许相互重叠。例如 ababa 中出现了 2 次 aba,位置依次为 0 和 2。
对于第二类和第三类操作,输出操作后的结果字符串。
输入样例
10
ababa
1 a
1 aba
1 aca
2 0 X
2 6 Y
2 3 M
3 2 6
3 4 4
1 aa
3 0 7
输出样例
0 2 4
0 2
-1
Xababa
XababaY
XabMabaY
XaabaMbY
XaabaMbY
1
YbMabaaX
数据约定
题目中设置三个单一操作的数据,对应三种不同的操作,三个数据加起来分配不超过 75% 的分数。
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
大字符串,会用insert,find,reverse就是水题
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
string s;
cin>>s;
while(n--){
int type;
cin>>type;
if(type==1){
string Find;
cin>>Find;
int cnt=0;
int start=0;
while(cnt<3){
size_t pos=s.find(Find,start);
if(pos==string::npos){
break;
}
cout<<(cnt?" ":"")<<pos;
start=pos+1;
cnt++;
}
cout<<endl;
}else if(type==2){
int p;
string s2;
cin>>p>>s2;
string Front=s.substr(0,p);
string Back =s.substr(p);
s=(Front+s2+Back);
cout<<s<<endl;
}else if(type==3){
int l,r;
cin>>l>>r;
reverse(s.begin()+l,s.begin()+r+1);
cout<<s<<endl;
}
}
return 0;
}
L2-1 姥姥改作业
分数:25
🔖 本题小目录题目描述

简而言之,面对 n 本学生作业,姥姥批改作业的策略是这样的:
1. 为每一本作业定义一个“混乱指数” c_i(i=1,2,⋯,n);
2. 为自己定义一个不可以接受的混乱指数阈值 T;
3. 当看到一本作业的 c_i > T,则先放到一边,即将这个作业本叠放在自己左右手边的作业本堆 S_left 上;
4. 对于 c_i ≤ T 的作业,批改之后叠放在自己左右手边的作业本堆 S_right 上;
5. 当面前没有待批改的作业本时,如果左手边还有一堆作业本,则调整自己的阈值 T 为这堆作业的混乱指数的平均值的向下取整,然后开始批改;
6. 重复上述步骤,直到所有作业都被批改完成。
问:姥姥批改作业的顺序是怎样的?
输入格式
输入第一行给出 2 个不超过 10^3 的正整数:n 为作业本的数量,T 为姥姥可以接受的混乱指数阈值。随后一行给出 n 个不超过 10^3 的非负整数,按原始作业堆自顶向下的顺序,第 i 个数字对应编号为 i 的作业的混乱指数(i=1,2,⋯,n)。同行数字间以一个空格分隔。
输出格式
按照姥姥批改作业的顺序,在一行中输出每个作业本的编号。数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例
10 2
233 8 1 6 0 745 2 555 42 3
输出样例
3 5 7 10 9 4 2 1 8 6
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 256 MB |
| 栈限制 | 8192 KB |
思路
先按初始阈值 T 把作业分成两类:大于 T 的放进左堆,小于等于 T 的直接批改并加入答案。等当前这一轮处理完,如果左堆还有作业,就把左堆作为新的待处理序列,阈值更新为左堆混乱指数平均值的向下取整,再继续按同样规则分流。
实现时要注意左堆是“堆栈”式处理,下一轮需要按原顺序逆转后再重新判断,最终按批改顺序输出编号即可。
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n,T;
cin>>n>>T;
vector<pair<int,int>> CC(n);
for(int i=0;i<n;i++){
cin>>CC[i].first;
CC[i].second=i+1;
}
vector<int> res;//结果堆
vector<pair<int,int>> curHun;//当前混乱堆
for(int i=0;i<n;i++){
if(CC[i].first>T){
curHun.push_back(CC[i]);//塞到混乱区
//初始化当前混乱堆
}else{
res.push_back(i+1);//
}
}//初次分类
if(curHun.empty()){
for(int i=0;i<n;i++){
if(i)cout<<' ';
cout<<res[i];
}
cout<<endl;
return 0;
}
vector<pair<int,int>> nextHun=curHun;//下一次混乱堆
while(!(nextHun.empty()&&curHun.empty())){
//只要有一堆还没空
reverse(nextHun.begin(),nextHun.end());
curHun=nextHun;
nextHun={};
int ave=0;
for(int i=0;i<curHun.size();i++){
ave+=curHun[i].first;
}
ave/=(curHun.size());
for(int i=0;i<curHun.size();i++){
if(curHun[i].first>ave){
//大于平均值的塞一边
nextHun.push_back(curHun[i]);
}else{
res.push_back(curHun[i].second);
//curHun.erase(curHun.begin()+i);
}
}
if(nextHun.empty()){
break;
}
}
for(int i=0;i<n;i++){
if(i)cout<<' ';
cout<<res[i];
}
cout<<endl;
return 0;
}
L2-2 超参数搜索
分数:25
🔖 本题小目录题目描述
输入格式
输入第一行给出正整数 n(1<n≤10^5),为所有在验证集上跑过的参数组合的总量。于是我们将所有参数组合从 1 到 n 进行编号。第二行给出 n 个区间 [0,10^8] 内的整数,第 i 个数字表示编号为 i 的参数组合的性能得分。随后一行给出正整数 m(≤n/2),为工程师查询次数。接下来 m 行,每行给出一个查询的目标性能得分 x,同样在区间 [0,10^8] 内。
输出格式
首先第一行按升序列出所有性能得分最高的参数组合的编号。同行数字间以 1 个空格分隔,行首尾不得有多余空格。
随后对每一次查询 x,我们需要从所有性能得分大于 x 的参数组合中,找到并输出那个得分最小的组合编号。如果这样的参数组合不唯一,则输出编号最小的解。如果这样的参数组合不存在,则输出 0。
输入样例
10
87 91 65 72 95 84 77 95 91 85
3
87
75
95
输出样例
5 8
2
7
0
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 256 MB |
| 栈限制 | 8192 KB |
思路
题目理解
有 n 个参数组合,编号 1到n,每个有一个性能得分(整数,0到1e8)。
第一问:输出所有 最高得分 的参数组合编号,按编号升序。
第二问:给出 m 个查询,每个查询给出目标值 x。
在所有 得分大于 x 的组合中,找到 得分最小 的那个组合。
如果这样的组合有多个(得分相同),取 编号最小 的。
如果不存在,输出 0。
只要有二分就实现了
可以把所有组合按 (得分, 编号) 排序,默认排序规则就是先按得分升序,得分相同按编号升序。
排序后,对于查询 x,只需找到第一个 得分 > x 的位置。
由于相同得分已经按编号升序排列,这个位置上的组合就是:
得分是大于 x 的最小得分
且在该得分组里编号最小
二分查找(upper_bound 或手写)即可。如果没找到(所有得分都 ≤ x),输出 0。
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
vector<pair<ll,ll>> arr(n);
ll Max=LLONG_MIN;
ll Min=LLONG_MAX;
for(int i=0;i<n;i++){
cin>>arr[i].first;
Max=max(Max,arr[i].first);
arr[i].second=i+1;
}
vector<pair<ll,ll>> temp=arr;//备用
sort(arr.begin(),arr.end());
for(int i=0;i<n;i++){
if(arr[i].first==Max){
cout<<arr[i].second;
if(i!=n-1){
cout<<" ";
}
}
}
cout<<endl;
int m;
cin>>m;
while(m--){
ll x;
cin>>x;
bool Found=false;
int l=0,r=n;
int ans=0;
while(l<r){
int mid=l+(r-l)/2;
if(arr[mid].first>x){
Found=true;
ans=arr[mid].second;
r=mid;
}else{
l=mid+1;
}
}
if(!Found){
cout<<0<<endl;
}else{
cout<<ans<<endl;
}
}
return 0;
}
L2-3 森林藏宝图
分数:25
🔖 本题小目录题目描述
为了方便规划,姥姥给每个有分叉的路口、以及每个藏宝地都做了编号,其中森林的入口编号为 0。略加研究后,姥姥有了一个重要的发现:如果我们一路向前不走回头路,那么从 0 号入口到每个藏宝地的路径都是存在且唯一的!换言之,我们不可能从两条不同的岔路殊途同归地走到同一个藏宝地。此外,从入口沿任何一条小路一直走到尽头,都会到达一个藏宝地。
姥姥不打算冒太大风险,所以只打算沿着安全系数比较大的路走。本题就请你帮个忙,看看如果只考虑途经最小的安全系数最大的路径,有可能取到哪些宝藏?即从 0 号入口到该藏宝地路径上,所有小路安全系数的最小值最大。
输入格式
输入在第一行给出图中标记的顶点总数 n(1<n≤10^5)
如题面所述,森林的入口编号为 0,其它节点(分叉路口和藏宝地)的编号从 1 到 n−1。随后 n−1 行,第 i(1≤i<n)行给出编号为 i 的节点的前驱节点的编号 j、以及从 j 到 i 这条小路的安全系数 sji(0≤sji≤100)。一行中的数字间以空格分隔。
注:所谓节点 i 的“前驱节点”,是指从 0 号入口出发,到达 i 之前所到达的那个节点。因为从 0 号入口到每个藏宝地的路径都是不唯一的,容易证明每个节点的前驱节点也是唯一的。
输出格式
首先在第一行输出解的途经最小安全系数的最大值 —— 所谓“解”,即按题目要求给姥姥推荐的藏宝地,也就是从 0 号入口出发,到该藏宝地路径上所有小路安全系数的最小值最大。
第二行按递增顺序输出解的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例
9
0 30
0 10
0 0
1 8
1 15
2 20
4 40
5 10
输出样例
10
6 8
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 64 MB |
| 栈限制 | 8192 KB |
思路
题目重述
有一张森林藏宝图,入口编号为 0。
每个节点(岔路口或藏宝地)都有唯一的前驱节点,所以整个地图实际上是一棵 有根树(根为 0)。
每条边有一个安全系数(0~100)。
从根到每个叶子节点(藏宝地)的路径是唯一的。
定义一条路径的“安全值” = 该路径上所有边权的最小值(最危险的那段决定整体风险)。
现在想找一个藏宝地,使得从根到它的路径安全值 尽可能大。
输出这个最大值,以及所有达到该最大值的藏宝地编号(递增)。
本质理解
这是一个 树上的“最大瓶颈路径”问题。
等价于:在所有根到叶子的路径中,找出 路径上边权最小值 最大的那些叶子。
换句话说:
每条路径的“弱点”是它最小的那条边。
我们想让这个“弱点”尽可能强。
然后输出这些“最强弱点”对应的藏宝地。
解题思路
-
建树
输入给出了每个非根节点的父节点和边权,直接建邻接表(存孩子和边权)。
根为 0,叶子节点就是没有孩子的节点。 -
遍历树,计算每条路径的瓶颈值
从根开始 DFS 或 BFS,同时维护 从根到当前节点的路径上的最小边权。
初始时,根节点的当前最小边权可以设为一个大数(如 114),因为取 min 时会变成实际边权。
每向下走一条边 w,更新 curMin = min(curMin, w)。
- 记录最优解
遇到叶子节点时:
如果 curMin > bestMin:更新 bestMin,清空结果列表,加入当前叶子。
如果 curMin == bestMin:直接加入结果列表。
如果 curMin < bestMin:忽略。
- 输出
先输出 bestMin,再将结果列表排序后输出。
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
int main(){
int n;
cin>>n;
vector<vector<pair<int,int>>> graph(n);
for(int i=1;i<n;i++){
int j,s;
cin>>j>>s;
graph[j].emplace_back(i,s);
}
stack<pair<int,int>> stk;
stk.push({0,114});
int bestMin=-1;
vector<int> res;
while(!stk.empty()){
auto [node,curMin]=stk.top();//获取当前节点和当前路径上的最小权值
stk.pop();
if(graph[node].empty()){
//如果这个节点的子节点是空的
//说明是叶子节点
if(bestMin<curMin){//结果还可以更新
bestMin=curMin;
res.clear();//那就可以全清了
res.push_back(node);
}else{
if(curMin==bestMin){
res.push_back(node);
}
}
}else{
//不是叶子节点
for(auto &[child,ss]:graph[node]){
int newMin=min(ss,curMin);//在下一个节点的权值和当前最小权值里找一个最小的
stk.push({child,newMin});
}
}
}
cout<<bestMin<<endl;
sort(res.begin(),res.end());
for(int i=0;i<res.size();i++){
if(i)cout<<" ";
cout<<res[i];
}cout<<endl;
return 0;
}
L2-4 大语言模型的推理
分数:25
🔖 本题小目录题目描述
输入格式
输入第一行给出正整数 n(1<n≤10^5),为所有在验证集上跑过的参数组合的总量。于是我们将所有参数组合从 1 到 n 进行编号。第二行给出 n 个区间 [0,10^8] 内的整数,第 i 个数字表示编号为 i 的参数组合的性能得分。随后一行给出正整数 m(≤n/2),为工程师查询次数。接下来 m 行,每行给出一个查询的目标性能得分 x,同样在区间 [0,10^8] 内。
输出格式
首先第一行按升序列出所有性能得分最高的参数组合的编号。同行数字间以 1 个空格分隔,行首尾不得有多余空格。
随后对每一次查询 x,我们需要从所有性能得分大于 x 的参数组合中,找到并输出那个得分最小的组合编号。如果这样的参数组合不唯一,则输出编号最小的解。如果这样的参数组合不存在,则输出 0。
输入样例
10
87 91 65 72 95 84 77 95 91 85
3
87
75
95
输出样例
5 8
2
7
0
限制
| 项目 | 限制 |
|---|---|
| 代码长度 | 16 KB |
| 时间限制 | 400 ms |
| 内存限制 | 256 MB |
| 栈限制 | 8192 KB |
思路
题意简述
给定一个 n 个节点的有向图,每条边有一个权值(代表概率)。从某个起点出发,每次在当前节点的所有未访问过的后继节点中,选择权值最大的那个;若权值相同则选择编号最小的。重复此过程直到无后继或所有后继均已访问。对每个查询输出行走的节点路径。
图的存储:邻接表,每个元素为 (to, weight)。
对每个查询:
标记 visited 数组,记录当前 DFS 路径已访问的节点(注意:每次查询独立重置)。
递归或循环模拟选择过程:
遍历当前节点的所有邻接点,选出满足 !visited[to] 且 weight 最大(次关键码为 to 最小)的节点。
若找到则继续,否则终止。
输出路径。
代码(c++)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
vector<bool> visited;
vector<int> result;
void DFS(int idea,vector<vector<pair<int,int>>> &graph){
result.push_back(idea);
visited[idea]=true;
int next=INT_MAX;
int maxP=-1;
if(graph[idea].empty()){//没有子节点
return;
}
for(auto &[nex,curP]:graph[idea]){
if(curP>maxP&&!visited[nex]){
maxP=curP;
next=nex;
}
if(curP==maxP&&nex<next&&!visited[nex]){
next=nex;
}
}
if(next!=INT_MAX&&maxP!=-1){//防止bug,理论不会产生
DFS(next,graph);
}else{
return;
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<pair<int,int>>> graph;//graph[u]表示从u开始的节点,graph[u]由数个{v,w}组成
//每个{v,w}表示从u到v的权值,也就是概率p
graph.resize(n+1);//从1-n编号
while(m--){
int id1,id2,p;
cin>>id1>>id2>>p;
graph[id1].emplace_back(id2,p);
}
int k;
cin>>k;
while(k--){
int idea;
cin>>idea;
visited.assign(n+1,false);
result.clear();
DFS(idea,graph);
for(int i=0;i<result.size();i++){
if(i){
cout<<"->";
}
cout<<result[i];
}
cout<<endl;
}
return 0;
}
注:L3题目难度较大,依旧第一题能做二三题送命
到时候会附上多一点图片和b站视频链接

2788

被折叠的 条评论
为什么被折叠?



