洛谷P3842线段【JAVA实现】

本文介绍了一种使用动态规划解决线段行走问题的方法,通过设置dp[i][0/1]来记录走到第i层线段并站在左/右端点上的最短长度,利用边界条件和递推公式实现了问题的高效求解。

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

题面

分析


只要弄懂每下一层时起点要不是上一层的左端点或者右端点。就是一个简单的DP

设dp[i][0/1],表示走到第i层的线段并站在左/右端点上所需要走的最短长度。
设L[i],R[i].表示第i层端点位置。
边界情况:dp[1][0/1]可以直接求的。注意走完线段之后到左右端点
显而易见dp公式
dp[i][0/1]=Math.min(dp[i-1][0]+Math.abs(L[i-1]-R/L[i])+R[i]-L[i],dp[i-1[1]+Math.abs(R[i-1]-R/L[i])+R[i]-L[i])+1;

代码


import java.util.Scanner;

public class Main{
	static int n,m;
	static int l[],r[]; //左右端点
	static int f[][];	//dp
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();l=new int[n+1];r=new int[n+1];
		f=new int[n+1][2];
		for (int i =1; i <=n; i++) {
			l[i]=sc.nextInt();r[i]=sc.nextInt();
		}
		f[1][0]=r[1]+r[1]-l[1]-1;f[1][1]=r[1]-1; //边界
		for (int i =2; i <=n; i++) {	
			f[i][0]=Math.min(f[i-1][0]+Math.abs(l[i-1]-r[i])+r[i]-l[i],f[i-1][1]+Math.abs(r[i-1]-r[i])+r[i]-l[i])+1;
			f[i][1]=Math.min(f[i-1][0]+Math.abs(l[i-1]-l[i])+r[i]-l[i],f[i-1][1]+Math.abs(r[i-1]-l[i])+r[i]-l[i])+1;
		}
		//选出最短距离。从最后一层的左右端点到(n,n)
		System.out.println(Math.min(f[n][1]+n-r[n],f[n][0]+n-l[n]));
	}
}

### 解析 P3842 线段树题目 #### 题目背景与描述 平台上的编号为P3842的题目涉及线段树的应用。这类问题通常围绕着一系列的操作,这些操作可能包括查询区间的最值、求和或是更新某些特定位置的数据等。对于具体编号为P3842的问题而言,其核心在于通过构建并维护一棵线段树来高效解决给定的任务。 #### 数据结构的选择——线段树 为了应对频繁发生的区间修改以及询问需求,在此选择了线段树作为主要数据结构[^1]。线段树能够支持快速地对数组中的某个范围执行批量更改,并在此基础上保持高效的查询性能。这使得即使面对较大的输入规模也能保证算法的时间效率处于可接受范围内。 #### 动态规划与时间复杂度分析 当涉及到动态规划(DP)时,如果单纯依靠暴力方法逐一遍历所有可能性,则会面临极高的计算成本。然而借助于线段树优化后的DP方案可以显著降低这一开销至\(O(n\ log\ n)\)[^2]。这意味着在整个过程中不仅实现了功能性的增强同时也兼顾到了运行速度的要求。 #### 实现细节 针对该类问题的具体实现方式如下所示: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 7; int a[MAXN], tree[MAXN << 2]; void pushUp(int rt){ tree[rt] = max(tree[rt<<1],tree[rt<<1|1]); } // 建立线段树 void build(int l,int r,int rt,vector<int>& nums){ if(l==r){ tree[rt]=nums[l]; return ; } int m=(l+r)>>1; build(l,m,rt<<1,nums); build(m+1,r,rt<<1|1,nums); pushUp(rt); } // 更新节点值 (lazy propagation 可选) void updateRange(int L,int R,int C,int l,int r,int rt){ if(L<=l&&r<=R){ // 进行相应更新逻辑 return ; } int m=(l+r)>>1; if(L<=m)updateRange(L,R,C,l,m,rt<<1); if(R>m)updateRange(L,R,C,m+1,r,rt<<1|1); pushUp(rt); } ``` 上述代码片段展示了如何建立一颗基于给定点集`nums`的线段树,并提供了用于更新指定区间内元素的方法框架。实际应用中还需要根据具体的业务场景调整内部逻辑以满足不同类型的请求处理需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值