团体程序设计天梯赛-练习集 -- L2-014. 列车调度(线段树)

本文探讨了一道经典的列车调度问题,旨在通过最少数量的轨道实现列车的有序进出站。使用了线段树来解决区间最大值问题,并通过贪心策略确定轨道上的列车顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

L2-014. 列车调度

时间限制
300 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

火车站的列车调度铁轨的结构如下图所示。


Figure

两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?

输入格式:

输入第一行给出一个整数N (2 <= N <= 105),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。

输出格式:

在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。

输入样例:
9
8 4 2 5 3 9 1 6 7
输出样例:
4
大体题意:
给你n 个火车排队进入火车轨道,要求最终出来的是从大到小排序的!
问中间最少需要多少条轨道数。(大体上是这样,在仔细读读能理解的!)
思路:
方案数很多,方法也很多。
上面的样例可以有下面这一种情况:
9 7
8 6
5 3 1
4 2
仔细想想可以知道:每一条火车轨道上肯定是递减排列的,因此可以采用贪心策略:
先放大火车,放完大火车为了尽可能重复利用这一条轨道,那么在找这个火车后面的最大的火车(也就是离这个火车最近并且不大
于他的火车)。
这样依次找下去即可!
这样,这个问题就转换到了 求区间的最值问题(线段树)
详细见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 100000 + 10;
int a[maxn];
int sum[maxn<<2];
int cnt;
void pushup(int rt){
    sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt){
    if (l == r){
        sum[rt] = a[++cnt];
        return ;
    }
    int m = (l+r) >>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
    if (L <= l && r <= R){
        return sum[rt];

    }
    int m = (l+r) >> 1;
    int ret = -maxn-10;
    if (L <= m) ret = max(ret,query(L,R,l,m,rt<<1));
    if (m < R) ret = max(ret,query(L,R,m+1,r,rt<<1|1));
    return ret;
}
void update(int p,int add,int l,int r,int rt){
    if (l == r){
        sum[rt] = add;
        return ;

    }
    int m = (l+r) >>1;
    if (p <= m)update(p,add,l,m,rt<<1);
    else update(p,add,m+1,r,rt<<1|1);
    pushup(rt);
}
int pos[maxn];
int main(){


    int n;
    scanf("%d",&n);
    for (int i = 1; i <= n; ++i)scanf("%d",&a[i]),pos[a[i]] = i;
    build(1,n,1);
    int sum = 0,ans=0;
    while(sum < n){
        int l = 1;
        while(l <= n){
            int cur = query(l,n,1,n,1);
            if (cur < 0)break;
            ++sum;
            l = pos[cur];
            update(l,-maxn,1,n,1);
            ++l;
        }
        ++ans;
    }
    printf("%d\n",ans);
    return 0;
}



### 关于团体程序设计天梯赛 Python L2 练习题解决方案 #### 题目背景 团体程序设计天梯赛是一项面向高校学生的编程竞赛活动,其题目难度分为多个级别,其中L2级别的题目通常涉及较为复杂的算法数据结构应用。以下是针对L2级别的Python练习题及其解决方案的探讨。 --- #### 图着色问题分析与解决方法 图着色问题是经典的NP完全问题之一,目标是在给定无向图 \( G = (V, E) \) 中,判断是否可以用 \( K \) 种颜色为每个顶点分配一种颜色,使得任意两相连边上的顶点颜色不同[^2]。 ##### 输入解析 根据引用描述,输入包含三部分: 1. **图形基本信息**:\( V \), \( E \), \( K \),分别代表顶点数、边数可用颜色数量。 2. **边信息**:接下来 \( E \) 行提供每边连接的两个节点编号。 3. **待验证的颜色配置方案**:共有 \( N \) 个方案,需逐一校验这些方案的有效性[^3]。 ##### 实现逻辑 为了实现该功能,可以采用邻接矩阵存储图结构并逐项检验各配色方案: 1. 构建邻接矩阵 `adj_matrix` 来记录哪些顶点之间存在边关系; 2. 对每一组颜色分配方案进行遍历,检查是否存在冲突情况(即相邻顶点共享相同颜色)。 下面是基于上述思路编写的Python代码示例: ```python def check_coloring(v_count, edges, k_colors, color_schemes): # 初始化邻接矩阵 adj_matrix = [[False]*v_count for _ in range(v_count)] # 填充邻接矩阵 for u, v in edges: adj_matrix[u-1][v-1] = True adj_matrix[v-1][u-1] = True results = [] # 检查每个染色方案 for scheme in color_schemes: valid = True for i in range(v_count): for j in range(i+1, v_count): if adj_matrix[i][j] and scheme[i]==scheme[j]: valid = False break if not valid: break results.append(valid) return results if __name__ == "__main__": import sys input_data = sys.stdin.read().splitlines() line_index = iter(input_data) first_line = next(line_index).strip().split(' ') vertex_num, edge_num, colors_k = map(int,first_line[:3]) graph_edges = [tuple(map(int,next(line_index).strip().split())) for _ in range(edge_num)] schemes_n = int(next(line_index)) coloring_schemes = [ list(map(lambda c:int(c)-1, next(line_index).strip().split())) for _ in range(schemes_n) ] outcomes = check_coloring(vertex_num,graph_edges,colors_k,coloring_schemes) output_results = ['Yes' if res else 'No' for res in outcomes] print("\n".join(output_results)) ``` 此脚本读取标准输入流完成整个处理过程,并输出对应的结果字符串列表["Yes", "No"]来指示各个测试案例的成功与否状态。 --- #### 最长对称子串问题概述 最长对称子串是指在一个字符串中找到长度最大的连续字符序列,使其满足中心对称性质。对于这个问题,动态规划或者Manacher's Algorithm都是有效的求解策略[^1]。 由于您特别关注的是Python版本解答,这里推荐使用扩展法配合切片操作简化实现流程如下所示: ```python def longest_palindromic_substring(s: str) -> str: max_len = start_pos = end_pos = 0 def expand_around_center(lft_idx, rght_idx): nonlocal max_len, start_pos, end_pos while lft_idx >=0 and rght_idx<len(s) and s[lft_idx]==s[rght_idx]: current_length = rght_idx-lft_idx+1 if current_length>max_len: max_len = current_length start_pos,end_pos=lft_idx,rght_idx lft_idx -=1 rght_idx +=1 n=len(s) for idx in range(n): # 单独考虑奇偶两种可能的情况 expand_around_center(idx,idx) # Odd length palindromes centered at index 'idx' if idx<n-1 and s[idx]==s[idx+1]: expand_around_center(idx,idx+1)# Even length palindrome starting from indices ('idx','idx+1') return s[start_pos:end_pos+1] # Example Usage sample_string="babad" print(longest_palindromic_substring(sample_string)) # Output could be either "bab" or "aba". ``` 通过定义辅助函数expand_around_center(), 我们能够高效地探索以某个位置为中心的所有潜在回文候选者,并更新全局最优解直至扫描完整个原始字符串为止. --- #### 总结 以上展示了如何利用Python语言应对两道典型的L2级挑战项目—图着色判定以及寻找最大镜像片段的任务。两者均体现了良好的抽象思维能力扎实的数据结构基础的重要性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值