UVALive-4850 Installations
2017-10-17 20:38
281 查看
题目大意:
有若干任务, 每个任务有完成消耗的时间和截止的时间.
如果完成某个任务的时刻是t, 截止时间是d, 那么罚时就是max( 0 , t-d ), 现在求罚时最大的任务和次大的任务的罚时和最少是多少.
首先很快就可以想到一个贪心的方法: 按照时间限制d排序, 相同就按照安装时间s排序, 都从小到大, 扫一遍就可以了.
然后就会发现过不了样例.
那么我们来研究一下这个样例:
6
1 7
4 7
2 4
2 15
3 5
3 8
6个任务, 每一行前一个数是s, 表示完成消耗时间, 后一个数是d, 表示时间限制, 每个任务用Ji表示, 这个样例还有下面这个图来辅助解释:
它按照贪心的方法放的话最大和次大应该是J6和J2, 结果是8, 但是正确答案是J2和J6, 答案是7.
我们发现其实就是把J6和J2换了位置, 或者说, 是把J2放到了J6的后面.
但是只交换最大和次大明显是错的, 而把后面的放到前面来只会让大的更大, 那么我们唯一可能的方法就是把前面的放到后面来.
记一下罚时最大和次大的是哪两个任务, 然后去这两个靠后的一个的位置记为cd, 然后我们枚举cd前面的某一个移动到cd的后面, O( n )扫一遍计算答案, 更新答案, 不断移动. 再和完全不移动直接贪心的答案取min, 这样就可以得到答案了.
为什么是对的? 首先cd之后的部分是不受移动的影响的, 我们从前面取出来一个放到了cd的后面, 而在cd前面的要么截止时间靠前, 要么处理时间短, 放到cd后面只会成为新的最大值, 而旧的最大和次大其中一个会变成次大值, 就有可能会使答案变小( 答案是最大和次大的和 ).
为什么只移动一个? 因为把前面的放到cd后面, 结果变成最大, 如果再选一个绝对比原来的次大或者最大要大, 我们新增了两个更大的, 答案明显会更大, 所以只要选择一个交换.
这样复杂度就是O( n )枚举移动, O( n )计算每一种答案, 总复杂度O( n^2 ).
移动用链表实现.
代码如下:
有若干任务, 每个任务有完成消耗的时间和截止的时间.
如果完成某个任务的时刻是t, 截止时间是d, 那么罚时就是max( 0 , t-d ), 现在求罚时最大的任务和次大的任务的罚时和最少是多少.
首先很快就可以想到一个贪心的方法: 按照时间限制d排序, 相同就按照安装时间s排序, 都从小到大, 扫一遍就可以了.
然后就会发现过不了样例.
那么我们来研究一下这个样例:
6
1 7
4 7
2 4
2 15
3 5
3 8
6个任务, 每一行前一个数是s, 表示完成消耗时间, 后一个数是d, 表示时间限制, 每个任务用Ji表示, 这个样例还有下面这个图来辅助解释:
它按照贪心的方法放的话最大和次大应该是J6和J2, 结果是8, 但是正确答案是J2和J6, 答案是7.
我们发现其实就是把J6和J2换了位置, 或者说, 是把J2放到了J6的后面.
但是只交换最大和次大明显是错的, 而把后面的放到前面来只会让大的更大, 那么我们唯一可能的方法就是把前面的放到后面来.
记一下罚时最大和次大的是哪两个任务, 然后去这两个靠后的一个的位置记为cd, 然后我们枚举cd前面的某一个移动到cd的后面, O( n )扫一遍计算答案, 更新答案, 不断移动. 再和完全不移动直接贪心的答案取min, 这样就可以得到答案了.
为什么是对的? 首先cd之后的部分是不受移动的影响的, 我们从前面取出来一个放到了cd的后面, 而在cd前面的要么截止时间靠前, 要么处理时间短, 放到cd后面只会成为新的最大值, 而旧的最大和次大其中一个会变成次大值, 就有可能会使答案变小( 答案是最大和次大的和 ).
为什么只移动一个? 因为把前面的放到cd后面, 结果变成最大, 如果再选一个绝对比原来的次大或者最大要大, 我们新增了两个更大的, 答案明显会更大, 所以只要选择一个交换.
这样复杂度就是O( n )枚举移动, O( n )计算每一种答案, 总复杂度O( n^2 ).
移动用链表实现.
代码如下:
//made by Crazy01 #include<bits/stdc++.h> #define inf 1<<30 #define ll long long #define db double #define c233 cout<<"233"<<endl #define mem(s) memset(s,0,sizeof(s)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int N=550; using namespace std; struct lll{ int tim,lim; bool operator <(const lll &a)const{ return lim==a.lim?tim<a.tim:lim<a.lim; } }job ; int n,T,ans,cd,r ; inline int gi(){ int x=0,res=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();} while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*res; } void init(){ n=gi(); r[0]=1; for(int i=1;i<=n;i++) job[i].tim=gi(),job[i].lim=gi(),r[i]=i+1; sort(job+1,job+1+n); } int calc(){ int t=0,max1=0,max2=0; cd=0; for(int i=r[0];i<=n;i=r[i]){ t+=job[i].tim; int tle=max(0,t-job[i].lim); if(tle>max1)max2=max1,max1=tle,cd=i; else if(tle>max2)max2=tle,cd=i; } return max1+max2; } void work(){ if(!ans){printf("%d\n",ans); return;} for(int i=r[0],end=cd;i<end;i=r[i]){ r[i-1]=r[i]; r[i]=r[end]; r[end]=i; ans=min(ans,calc()); r[end]=r[i]; r[i]=r[i-1]; r[i-1]=i; } printf("%d\n",ans); } int main(){ T=gi(); while(T--){ mem(job); init(); ans=calc(); work(); } return 0; }
相关文章推荐
- UVALive 4850 Installations
- UVALive 4850 Installations
- uvalive 4850(贪心)
- Beijing Guards UVALive - 3177 (二分)
- UVaLive 7500 Boxes and Balls (数学)
- Cross the Wall UVALive - 5097 (贪心+斜率dp)
- UVALIVE 3786 Fairies' Defence
- POJ1060 HDU1343 ZOJ1026 UVALive2323 Modular multiplication of polynomials(多项式模2除)
- 秦始皇修路(uvalive 5713)
- UVALive 6915 Leveling Ground 倍增RMQ
- UVALive2678 UVA1121 Subsequence【前缀和+二分搜索+尺取法】
- UVALive - 6529 找规律+dp
- UVALive3638 UVA12100 POJ3125 HDU1972 Printer Queue【队列+模拟】
- UVALive - 7263 Today Is a Rainy Day (BFS预处理)
- UVALive 4235 Recursively Palindromic Partitions
- UVALive 5862 City Travel 解题报告
- 4000 UVALive - 6862 Triples(数学分析)
- E - Inside, Outside or On UVALive - 7004
- UVALive 4868 Palindrometer 暴力
- UVALive - 3942(前缀树DP)