CodeForces 614D 二分+贪心
来源:互联网 发布:万网域名怎么转让 编辑:程序博客网 时间:2024/05/16 11:38
原题链接:http://codeforces.com/problemset/problem/614/D
题意:有n门学科,每一门最高水平为A,一共可以提高的水平为m,计算经过提升后的最大得分,得分=(达到A分数的科目个数)*cf+(最低分数)*cm
最开始真的一脸懵逼完全不会啊
仔细想了想,可以枚举达到A的数目,把原数组从小到大排个序倒着选择成为满分的科目,然后在剩下没达到满分的科目里选择最低分。复杂度应该可以接受,我最开始想也是暴力枚举最低分判断合法好了,后来发现尼玛这不就是二分嘛
然后就愉快【呵呵】地开始码了
在check的时候真的饶了很久,最后发现其实预处理一个前缀和就很好计算了。要注意时刻维护你剩下的可以提高的分数【要保证这个值不能为负数】,至于计算的话用lower_bound找到第一个大于等于这个最小值的位置,然后就很好计算了。
多简单是吧,然后介绍我漫长【脑残】的调试过程:
1.最开始的数组要排序嘛,又要计算前缀和吗,我当时为了少打一个for循环就边读入边处理了,呵呵,错在哪多明显【于是WA在了第一个点】
2.考虑的ans的最初答案【就是不做任何改变】,但是,我没有考虑一个满分都没有的情况,最开始我想直接加到for循环里,发现不行【因为会导致j的计算少1】就只能在前面又加了一个二分最低分【于是WA在了第三个点】
然后这一天我就去睡了。= =
3.以上改完以后WA在了第五个点,好,我查。此时是晚自习。
发现第一次二分的时候求pos的时候没有考虑越界情况,于是当n=1的时候就挂了
4.接下来卡在了第19个点。我选择了找一只标程对拍。发现自己的输出答案有问题(虽然这不是我WA这个点的原因)我改写a2的地方竟然写了low。。。之后还有一个问题没找到错在哪。。
这只是一个小插曲,改了之后依旧错了,我发现我错的不是输出分数,而是输出最大得分,我的答案小了?(感谢codeforces给看数据)
漫长的查答案,不断地调整二分上下界,没用。。。
回家。
打开我的vim,打开614D的cpp,突然灵光一闪——
lower_bound()求的是大于等于的第一个数,那么我在统计小于这个数的时候是需要减1的啊啊啊啊啊啊啊啊啊啊啊啊
5.好了我A了【终于quq】
好有成就感啊,再一次见识了什么叫信息学竞赛的细节。。。。。
不过我的速度比某位dalao慢了一倍,仔细查看发现是我们二分的东西不一样,我二分的是最低分,他二分地是科目范围,从数据范围来看,前者是log(10^9),后者是log(10^5)。。。
激动到写博客留恋,虽然不是一道非常难的题。
以下AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<cmath>#define maxn 100010#define ll long longusing namespace std;typedef pair<ll,int> P;P a[maxn];int n,cf,cm;ll A,m;ll sum[maxn];struct node{ int id;ll x; bool operator <(node s)const{ return id<s.id; }}out[maxn];void file(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout);}bool cmp(P a,P b){ return a.first<b.first;}int main(){ //file(); scanf("%d%I64d%d%d%I64d",&n,&A,&cf,&cm,&m); int cnt=0;ll minn=1e18+7; for(int i=1;i<=n;i++){ scanf("%I64d",&a[i].first); a[i].second=i;minn=min(minn,a[i].first); if(a[i].first>=A)cnt++; } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].first; ll tp=m;ll ans=cnt*cf+minn*cm;int a1=cnt;ll a2=minn; ll low; ll l=1,r=A; while(l<=r){ ll mid=(l+r)>>1; int pos=lower_bound(a+1,a+n+1,P(mid,0))-a-1; pos=min(pos,n); ll cost=pos*mid-sum[pos];//printf("%lld %d %lld\n",mid,pos,cost); if(cost>m)r=mid-1; else low=mid,l=mid+1; } ll tp2=low*cm; if(tp2>ans){ ans=tp2;a1=0;a2=low; } low=0;tp=m; for(int i=n,j=1;i>=1;i--,j++){ tp-=(A-a[i].first);//printf("%d %lld\n",i,tp); if(tp<0)break; ll l=1,r=A;low=0; while(l<=r){ ll mid=(l+r)>>1; int pos=lower_bound(a+1,a+n+1,P(mid,0))-a-1; pos=min(pos,i-1); ll cost=pos*mid-sum[pos]; //printf("(%lld %lld %d %d %d %lld %lld\n",mid,a[i].first,i,j,pos,cost,tp); if(cost>tp)r=mid-1; else l=mid+1; } low=l-1; ll tp2=low*cm+j*cf;//printf("1.%lld\n",tp2); if(tp2>ans){ //printf("%d %d %d %lld %lld\n",tp,i,j,low,tp2); ans=tp2;a1=j;a2=low; } } printf("%I64d\n",ans); //printf("(%lld %lld\n",a1,a2); for(int i=n;i>=n-a1+1;i--){ out[i].x=A; } for(int i=1;i<=n-a1;i++){ // if(a[i].second==1)printf("*%lld\n",a[i].first); out[i].x=max(a[i].first,a2); } for(int i=1;i<=n;i++)out[i].id=a[i].second; sort(out+1,out+n+1); for(int i=1;i<=n;i++){ if(i!=n)printf("%I64d ",out[i].x); else printf("%I64d\n",out[i].x); } return 0;} /*1 100 1 2 3016231 3 5 10 1 51 3 12 6 0 1 45 155 53 5 10 1 3391 3 1*/
- CodeForces 614D 二分+贪心
- Codeforces 609D 贪心+二分
- codeforces 732D (二分 贪心)
- 【codeforces 732D】【二分+贪心】
- Codeforces #732D 二分 贪心
- CodeForces 363D 【二分+贪心】
- Codeforces 479D Long Jumps(贪心+二分)
- Exams Codeforces Round#377-D(贪心+二分)
- codeforces 377D exam贪心判定+二分
- codeforces 732D Exams(贪心+二分)
- codeforces 732D Exams 二分搜索 贪心
- Codeforces 732D Exams【二分+贪心】
- CodeForces 732D Exams 二分+贪心
- codeforces - 732D Exams 【二分 + 贪心】
- CodeForces 363D.Renting Bikes(二分+贪心)
- CodeForces 732 D.Exams(二分+贪心)
- Codeforces 732D Exams【贪心+二分】
- Codeforces 803D Magazine Ad【二分+贪心】
- angular4读取本地json文件
- React Native 的图片加载方式
- spring中packagesToScan的解释
- 【小技巧】桌面图标出现蓝色问号的怎么办?
- http协议无状态中的 "状态" 到底指的是什么?!
- CodeForces 614D 二分+贪心
- Java内存区域与内存溢出异常
- HDOJ HDU 1085 Holding Bin-Laden Captive!
- 高复用率的RTSPClient组件EasyRTSPClient调用说明
- hdu 6194
- 001_JavaWeb中文乱码问题
- http invoker
- 高复用率的RTSPClient组件EasyRTSPClient设计流程
- python 迭代器和生成器