是男人就做的50道题目 题解

------------------------------------------------------1-----------------------------------------------------------

     第一题没什么可说的,维护一个前缀和,然后很容易想到一个O(n^2)的算法,然后势必会超时。我们维护的前缀和的后面最大值减去前面的最小值既是答案,因此我们可以维护前面的最小值,向后更新答案,复杂度降为O(N)。

#include<cstdio>
#include<iostream>
using namespace std;
int n,sum,MIN,ans;
int s[100050];
int main()
{
	freopen("profits.in","r",stdin);
	freopen("profits.out","w",stdout); 
	ans=-999999999;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		s[i]=s[i-1]+x;
	}
	for(int i=1;i<=n;i++)
	{
		ans=max(ans,s[i]-MIN);
		if(s[i]<MIN)MIN=s[i];
	}
	printf("%d\n",ans);
	return 0;
}

---------------------------------------------------------2---------------------------------------------------------

   此题是最难的大水题,出题人不经意间加了个2让我迷茫的连样例都撸不过了。 正确的题意:在第K家买饲料,路上的费用第K家到家的距离*饲料数。

所以在每家商店买每一吨饲料的价格就固定了,为饲料本身的价格加上到家的距离。预处理一边后排序贪心即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=400;
int k,e,n,ct, 
	c[maxn],
 	x[maxn],
	f[maxn], 
	w[maxn*1000];
int main()
{
	freopen("feed2.in","r",stdin);
	freopen("feed2.out","w",stdout);
	scanf("%d%d%d",&k,&e,&n);
	for(int i=1;i<=n;i++)
	scanf("%d%d%d",&x[i],&f[i],&c[i]);
	
	for(int i=1;i<=n;i++)
	   for(int j=1;j<=f[i];j++)
		  w[++ct]=c[i]+(e-x[i]);
	sort(w+1,w+1+ct);
	int ans=0;
	for(int i=1;i<=k;i++)
	ans+=w[i];
	printf("%d\n",ans);
	return 0;
}

---------------------------------------------------------3---------------------------------------------------------

去年NOIP2013第二题就是借鉴了此题,贪心的思路完全一样。

对于任意的两头牛A和B,我们分别讨论A在B前面和B在A前面时的可能答案。

设A牛的体重为a,力量为b,B牛的体重为A,力量为B,AB两牛上面的牛重量和为SUM。

则A在B前面时:  ans=max(SUM-b,SUM+a-B);

    B在A前面时:  ans=max(SUM-B,SUM+A-b);

可以发现,SUM-b一定小于SUM+A-b,SUM-B一定小于SUM+a-B

所以当SUM+a-B也小于SUM+A-b时(既a+b<A+B),SUM-b和SUM+a-B就都小于SUM+A-b,因此我们选择A在B前面肯定比B在A前面更优。

同理当SUM+A-b也小于SUM+a-B时(既A+B<a+b),SUM-B和SUM+A-b就都小于SUM+a-B,因此我们选择B在A前面肯定比A在B前面更优。

所以我们发现,和小的排在前面肯定能使答案更优,因此我们就有了全局的贪心方案,所有的牛按体重和力量的和排序,和小的排在前面,然后从头到尾扫一遍更新答案。

这里必须要注意的细节问题(如果不注意将丢失大部分分数)  我们扫答案前定义的最大值的初始值不能为0,因为可能为负数。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50050;
struct node
{
	int w,s;
	bool operator < (node aa) const
	{
		return (w+s<aa.w+aa.s)||(w+s==aa.w+aa.s&&w<s);
	}
}a[maxn];
int n;
int main()
{
	freopen("acrobat.in","r",stdin);
	freopen("acrobat.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d%d",&a[i].w,&a[i].s);
	sort(a+1,a+1+n);
	if(n==1)
	{
		printf("%d",-a[1].s);
		return 0;
	}
	long long s=0,ans=-99999999;
	for(int i=1;i<=n;i++)
	{
		s+=a[i-1].w;
		if(s-a[i].s>ans)ans=s-a[i].s;
	}
	cout<<ans;
	return 0;
}
---------------------------------------------------------4---------------------------------------------------------





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值