1 条题解

  • 0
    @ 2026-4-28 16:11:01

    ::::info[题意]{open} 这题第一眼很像我前几天做的 P3076,但是该题是一次只能载一个乘客,而本题是可以同时载多个。

    有一条数轴,需要从 00 走到 MM,且路程必须包含 liril_i \rightarrow r_i1in1 \leqslant i \leqslant n),求最短路程。 ::::

    ::::info[分析]{open}

    本题是一道区间合并贪心问题。

    由于本题可以同时载多个乘客,而我们本来也是从 00 走到 MM,所以所有正方向的乘客都可以顺路送到。

    而对于负方向的乘客,要让往回绕的路程最短,需要找出怎么才能一次送尽量远的距离,而最短距离就是所有线段的交的长度的两倍(因为往返)。

    :::info[重叠区间证明]{open} 借用

    https://www.luogu.com.cn/user/907119

    对于 1122 这两个重叠区间,放在一段中往返路程为 2(r2l1)2(r_2-l_1),而单独往返为 $2(r_2-l_2)+2(r_1-l_1)=2(r_2-l_1)+2(r_1-l_2) \geqslant 2(r_2-l_1)$,故放在一段中往返不劣。 :::

    :::error[一个误区]{open} 答案为 M+2(maxi=1nrimini=1nli)M + 2(\max_{i=1}^n r_i-\min_{i=1}^n l_i)

    惨痛教训。 :::

    :::info[不重叠区间证明]{open} 再看这张图:

    对于 2233 这两个不重叠区间,如果分别往返,路程为 2(r3l3)+2(r2l2)2(r_3-l_3)+2(r_2-l_2),而放在一段中往返路程为 $2(r_3-l_2)=2(r_3-l_3)+2(l_3-r_2)+2(r_2-l_2) \geqslant 2(r_3-l_3)+2(r_2-l_2)$,故分别往返不劣。 ::: ::::

    ::::success[正确代码]{open}

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    #define INF 1e18
    
    struct node {
    	int s, t;
    	bool operator<(node x)const { return s < x.s; }
    };
    
    int n, m, n1;
    node a[300005];
    
    signed main() {
    	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    	
    	cin >> n >> m;
    	for(int i = 1, s, t; i <= n; ++ i) {
    		cin >> s >> t;
    		if(s > t) // 负方向才存!
    			a[++ n1] = {t, s};
    	}
    	
    	sort(a + 1, a + n1 + 1);
    	
    	int nows = a[1].s, nowt = a[1].t, ans = m; // nows,nowt 当前区间的始末
    	for(int i = 2; i <= n; ++ i){
    		if(a[i].s <= nowt) // 与当前区间重叠
    			nowt = max(nowt, a[i].t); // 延展区间
    		else
    			ans += 2 * (nowt - nows), nows = a[i].s, nowt = a[i].t; // 结算该区间答案,并更新区间位置
    	}
    	ans += 2 * (nowt - nows); // 别忘了!
    	
    	cout << ans;
    	
    	return 0;
    }
    

    ::::

    • 1

    信息

    ID
    4851
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者