0
点赞
收藏
分享

微信扫一扫

C. Hacker, pack your bags(区间不相交,长度和为定值)

君心浅语 2022-03-30 阅读 14
算法

题目链接:

Problem - 822C - Codeforces

题意:

有n种行程选择,第i种是开始日期是l,结束日期是r,包括第l天和第r天(共r-l+1天),花费为w,从其中选择两个完全不冲突的行程(即这两个行程完全不相交),使得两个行程相加刚好为x天,同时花费最少。若存在输出最小花费,否则输出-1。

思路:

题目要求选择两个区间,不相交且相加等于x。这里我们把所有端点从小到大排序, 如果碰到的这个端点是右端点,说明右端点对应的这个区间我已经走完了,用一个cost数组记录对应此区间长的最小花费(不断更新),如果这个点是左端点, 那么它可以加上前面已经走过的的区间中的差等于 x - 当前区间长 中花费最小的值(cost[x - 当前区间长])来跟当前的ans进行比较取最小。

trick:两个区间不相交要求端点也不能重合,故排序的时候,让左端点排在前面, 这样在遍历x这个点时,所有以x为右端点的区间都还没有更新cost。

样例

 代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int inf=2e9+10;
const int N=2e5+10;
int n,x;
int cost[N];
typedef struct Segment{
	int pos1;//主键
	int pos2;//区间的另一个点
	int co;//花费 
	int type;//标记主键是左端点(type=-1)还是右端点(type=1) 
}Segment;
Segment seg[N*2];

bool cmp(Segment x,Segment y){
	if(x.pos1==y.pos1)
		return x.type<y.type;
	return x.pos1<y.pos1;
}
int main(){
	scanf("%d%d",&n,&x);
	int l,r,w;
	int cnt=0;
	for(int i=1;i<=n;i++){
		scanf("%d %d %d",&l,&r,&w);
		seg[++cnt]={l,r,w,-1};
		seg[++cnt]={r,l,w,1};
	}	
	sort(seg+1,seg+cnt+1,cmp);
	int ans=inf,len;
	for(int i=1;i<cnt;i++){
		if(seg[i].type==-1){//左端点 
			len=seg[i].pos2-seg[i].pos1+1;
			if(x<len||cost[x-len]==0)
				continue;
			else
				ans=min(ans,seg[i].co+cost[x-len]);
		}
		else{
			len=seg[i].pos1-seg[i].pos2+1;
			if(cost[len]==0)
				cost[len]=seg[i].co;
			else
				cost[len]=min(cost[len],seg[i].co);
		}
	}
	if(ans==inf)
		printf("-1");
	else
		printf("%d",ans);
}
举报

相关推荐

0 条评论