1 条题解
-
0
自动搬运
来自洛谷,原作者为

longlinyu7
欲买桂花同载酒,终不似,少年游搬运于
2025-08-24 22:16:50,当前版本为作者最后更新于2023-11-28 21:56:09,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
分析题意
即有 条线段,选出 条线段,使得他们的交集长度最大并输出任意一种方案。
易知最终得到的区间是某一线段的左端点与另一线段的右端点。
解题思路
贪心
若先判断左端点,那将左端点按值从小到大排序,然后从前遍历即可。
优先队列
剩下只用判断右端点,需要维护 条线段的右端点值,那么用优先队列,可以比较方便的得出。针对该题,我们使用小根堆。
如何获得答案
维护合法右端点减去左端点的最大值,最后输出即可。
对于线段的编号,需要顺带维护最大长度的左端点与右端点,记为 和 。我们重新遍历一边,找到左端点小于等于 和右端点大于等于 的线段,输出即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=1000005; int n,k,tail,head,tim; struct node{int x,y,num;}a[N]; priority_queue<int,vector<int >,greater<int > >r;//小根堆 bool cmp(node a,node b){ return a.x==b.x?(a.y<b.y):(a.x<b.x); } int main(){ cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i].x>>a[i].y; a[i].num=i; } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++){ r.push(a[i].y); while(r.size() >k){ r.pop(); } if(r.size()==k){ //如果合法 if(tim<(r.top()-a[i].x)){//替换 tail=r.top();head=a[i].x; tim=tail-head; } } } cout<<tim<<endl; for(int i=1;i<=n;i++){//重新遍历 if(a[i].x<=head&&a[i].y>=tail&&k){ k--; cout<<a[i].num<<" "; } } return 0; }
- 1
信息
- ID
- 8353
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者