CCF202303-2 垦田计划

3 篇文章 0 订阅
2 篇文章 0 订阅

题目


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题本来就不是我能做得来的,试试经过一个月的训练能不能写写第三题吧。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awars_zpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值