70分:
贪心的话就先考虑t和c较大的一个,从t较大的开始减,这样的话就需要排序,而且每一次减完之后需要再拍一次顺序,可以想到使用优先队列加快重复的排序。
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=1e5+10;
int n,m,k;
struct node{
int t,c;
};
struct cmp{
bool operator() (node a,node b)
{
if(a.t==b.t) return a.c>b.c;
return a.t>b.t;
}
};
priority_queue<node,vector<node>,cmp> heap;
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
node temp;
cin>>temp.t>>temp.c;
heap.push(temp);
}
while(m)
{
node tp=heap.top();
if(tp.t<=k) break;
heap.pop();
m-=tp.c;
tp.t--;
heap.push(tp);
}
cout<<heap.top().t<<endl;
return 0;
}
70分的原因也是很明显,每次只操作一天,m是1e9量级肯定会超时。
100分PLAN1:
二分,很容易知道答案会出在【k,max(t[i])】中,所以只需要在这个区间内使用二分就可以找到答案,这样的时间复杂度就可以降到nlogn。
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
ll n,m,k;
ll t[100001],c[100001];
bool judge(ll x)
{
ll sum=0;
for(ll i=1;i<=n;i++)
{
if(t[i]>x) sum+=(t[i]-x)*c[i];
if(sum>m) return false;
}
return true;
}
int main()
{
cin>>n>>m>>k;
ll mx=0;
for(ll i=1;i<=n;i++)
{
cin>>t[i]>>c[i];
mx=max(t[i],mx);
}
ll l=k,r=mx;
ll ans=0;
while(l<=r)
{
ll mid=(l+r)/2;
//寻找最小的天数
if(judge(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
return 0;
}
100分PLAN2:
还是延续70分的思想,但是不再是一次操作只操作一天了,而是一次操作操作需要时间相同的那几天,一样从天数最大的开始,因为只有需要i天的那几天全部-1才能做到最后的结果ans-1。这样就需要一个数组存储时间是i天的总投入资源量。
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=1e5+10;
int n,m,k;
int t[N],c[N],sm[N];
int main()
{
cin>>n>>m>>k;
int mx=0;
for(int i=1;i<=n;i++)
{
cin>>t[i]>>c[i];
sm[t[i]]+=c[i];
mx=max(mx,t[i]);
}
int ans=mx;
for(ans=mx;ans>=k;ans--)
{
if(sm[ans]>m) break;
m-=sm[ans];
sm[ans-1]+=sm[ans];
if(ans==k) break;
}
cout<<ans<<endl;
return 0;
}
总得来说CCF的第二题的难度并不是非常得大,但是在考试中稳定拿下100分仍然需要练习,毕竟3,4,5题本来就不是我能做得来的,试试经过一个月的训练能不能写写第三题吧。