现在这里orz 暗い之殇 orz大佬的思路~本蒟蒻看懂了~
题目背景
买完了桶,桶哥要去送桶。
题目描述
桶哥买了nn个桶, 他要将这些桶送去nn个人的家。他送第ii个桶需要a_iai的时间,需要在b_ibi之前送到。桶哥很懒,他想要尽量晚起身去送桶。问他最晚什么时候要去送桶?
桶哥在送完一个桶之后可以紧接着去送另一个桶。
输入格式
一行一个整数nn,以下nn行每行两个整数表示a_iai, b_ibi.
输出格式
一行一个整数,表示桶哥最晚什么时候起身。
输入输出样例
4 1 6 2 7 2 8 1 7
2
说明/提示
样例说明:
桶哥在第2秒去送第1个桶,第3秒送到。
桶哥在第3秒去送第2个桶,第5秒送到。
桶哥在第5秒去送第4个桶,第6秒送到。
桶哥在第6秒去送第3个桶,第8秒送到。
不要问我他为什么会跑得那么快或那么慢。
对于20%数据,n \leq 10, 1 \leq a_i, b_i \leq 1000n≤10,1≤ai,bi≤1000
对于60%数据,n \leq 1000, 1 \leq a_i, b_i \leq 10^4n≤1000,1≤ai,bi≤104
对于100%数据,n \leq 10^6, 1 \leq a_i, b_i \leq 10^9n≤106,1≤ai,bi≤109
保证答案大于等于0.
思路详解
题目中强调了保证答案大于等于0,说明答案一定是有解的。
对于如何安排,运用小学的数学知识可的,尽量将任务向后安排,最好是卡在结束时间完成,这样的目的是为了避免与其他任务发生冲突,可以让其他任务继续合理安排,这样的话才是最优解。
贴着结束时间点了完成任务后,那么红色的那一部分我们就不用考虑了,因为做不了其他任务;
综上所述,可得到一下思路:
1,将结束时间从大到小排序,让结果sum等于最大的一个
2,用结果sum减掉结果所用的时间
开始划重点:3,将当前结果sum与其他任务的结束点比较,如果sum小于其他任意一个结束点的值,那么替换,用ans减掉对应时间
4,重复2的步骤一直到结束
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
图解:
1.找到一个结束时间最大的任务---任务一(结束时间为6),此时sum=6;减去当前任务所需的时间,更新ans=6-2=4;
2.来到了第二个任务:发现该任务的结束时间点为3,比当前的sum要小!于是我们更新sum=b2=3,再减去当前任务的时间,更新sum=3-1=2;
那么最后的答案就是2了!
多次模拟以后,我们就懂得其中的巧妙用意了:
还是上面的例子,如果第二步没有使sum=b2,那么我们就会这样放置第二个任务:
AC代码如下:
1 /*桶哥买了nn个桶, 他要将这些桶送去nn个人的家。他送第ii个桶需要a_ia的时间,需要在b_ib 之前送到。桶哥很懒,他想要尽量晚起身去送桶。问他最晚什么时候要去送桶? 2 输入格式 3 一行一个整数nn,以下nn行每行两个整数表示a_ia 4 输出格式 5 一行一个整数,表示桶哥最晚什么时候起身。*/ 6 #include<bits/stdc++.h> 7 using namespace std; 8 int re() 9 { 10 char ch=getchar(); 11 int a=0,x=1; 12 while(ch<'0'||ch>'9') 13 { 14 if(ch=='-') x=-x; 15 ch=getchar(); 16 } 17 while(ch>='0'&&ch<='9') 18 { 19 a=a*10+(ch-'0'); 20 ch=getchar(); 21 } 22 return a*x; 23 } 24 int n; 25 struct t 26 { 27 int da,ti; 28 }a[1000001]; 29 int cmp(t x,t y) 30 { 31 return x.da>y.da; 32 } 33 int main() 34 { 35 n=re(); 36 for(int i=1;i<=n;i++) 37 { 38 a[i].ti=re(); 39 a[i].da=re(); 40 } 41 sort(a+1,a+1+n,cmp); 42 long long sum=a[1].da; 43 for(int i=1;i<=n;i++) 44 { 45 if(sum>a[i].da) sum=a[i].da; 46 sum-=a[i].ti; 47 } 48 cout<<sum; 49 return 0; 50 }