石油大提交网址:http://exam.upc.edu.cn/problem.php?id=4203
4203: MJF wants to work
时间限制: 1 Sec 内存限制: 128 MB提交: 60 解决: 11
[提交][状态][讨论版]
题目描述
MJF feel the summer vacation is very leisure. So he wants to work to earn money.
There are n jobs MJF can take part in.For job i, it has the start time ti.x, the end time ti.y and reward ci.
MJF wants to take part in two jobs (exact two jobs), and he wants to earn exactly M yuan. He doesn't want to earn one money more,he thinks it's a waste.
Becase MJF is a lazy boy, so he wants the time of the sum of two jobs shortest.
Becase MJF can only take part in one job in a time.So two jobs can't overlap.(ti.y < tj.x)
There are n jobs MJF can take part in.For job i, it has the start time ti.x, the end time ti.y and reward ci.
MJF wants to take part in two jobs (exact two jobs), and he wants to earn exactly M yuan. He doesn't want to earn one money more,he thinks it's a waste.
Becase MJF is a lazy boy, so he wants the time of the sum of two jobs shortest.
Becase MJF can only take part in one job in a time.So two jobs can't overlap.(ti.y < tj.x)
输入
The input consists of multiple test cases.
For each test,the first line contains 2 integers n, m.(1 <= n, m <= 2e5)
Then following n lines, each line contains 3 integers ti.x, ti.y, ci.(1 <= ti.x, ti.y, ci <= 2e5)
For each test,the first line contains 2 integers n, m.(1 <= n, m <= 2e5)
Then following n lines, each line contains 3 integers ti.x, ti.y, ci.(1 <= ti.x, ti.y, ci <= 2e5)
输出
For each test case, print the value of the sum of two jobs' time.if there are no answer,please print"oh no!"
样例输入
3 10
1 2 3
3 4 7
4 6 7
1 10
1 10 10
样例输出
4
oh no!
【解析】:
把每一个区间的左右端点拆开,但要两端点都记住自己的money和time。
然后按时间先后排序,扫一遍,此过程中,遇到右端点,就存一下此工作结束后的钱数与所用时间(最小值)
这里用的是dp数组。dp[i]表示挣钱为i的工作所用的时间(最小)。
遇到左端点,就把这项工作与前面已经扫过的工作组合,加一下时间,不断更新ans(最小)
【代码】:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define mset(a,i) memset(a,i,sizeof(a))
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX=1e6+5;
struct node{
int p,flag;
int money;
int time;
}e[MAX*4];
int dp[MAX*2];
int n,m,cnt;
void add(int l,int r,int val)
{
e[cnt].p=l;
e[cnt].flag=0;//左端点
e[cnt].money=val;
e[cnt].time=r-l+1;
cnt++;
e[cnt].p=r;
e[cnt].flag=1;//右端点
e[cnt].money=val;
e[cnt].time=r-l+1;
cnt++;
}
bool cmp(node a,node b)
{
if(a.p==b.p)return a.flag<b.flag;//若左右端点同点,先处理左;
return a.p<b.p;//按端点排序
}
int solve()
{
sort(e,e+cnt,cmp);
mset(dp,INF);//dp[i]记录当赚钱为i时,所用的最小时间
int ans=INF;
for(int i=0;i<cnt;i++)
{
if(e[i].flag==0)//左
{
ans=min(ans,dp[m-e[i].money]+e[i].time);
}
else
{
dp[e[i].money]=min(dp[e[i].money],e[i].time);
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cnt=0;
for(int i=0;i<n;i++)
{
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
add(l,r,val);
}
int ans=solve();
if(ans==INF)
puts("oh no!");
else
printf("%d\n",ans);
}
}