贪心学习笔记
题面传送门
贪心一般和排序逃不开关系。这一道题目是普及组原题的弱化版。
首先我们列出答案的式子\(ans=\sum\limits_{i=1}^{n}{(a_i\times\sum\limits_{j=1}^{i}{b_j})}\)
乘法分配律,\(ans=\sum\limits_{i=1}^{n}{(a_i\times b_i+a_i\times \sum\limits_{j=1}^{i-1}{b_j})}\)
分配到每一个 \(s_i\),得\(s_i=a_i\times b_i+a_i\times \sum\limits_{j=1}^{i-1}{b_j}\)
若要比较两个 \(a_x\)与\(a_y\)的优先级关系,得\(a_x\times b_x+a_x\times \sum\limits_{j=1}^{x-1}{b_j}+a_y\times b_y+a_y\times \sum\limits_{j=1}^{y-1}{b_j}<a_y\times b_y+a_y\times \sum\limits_{j=1}^{y-1}{b_j}+a_x\times b_x+a_x\times \sum\limits_{j=1}^{x-1}{b_j}\)
两边同时消去,得\(a_x \times \sum\limits_{j=1}^{x-1}{b_j}+a_y\times \sum\limits_{j}^{y-1}{b_j}<a_y \times \sum\limits_{j=1}^{y-1}{b_j}+a_x\times \sum\limits_{j}^{x-1}{b_j}\)
再由于 \(y=x+1\),进行乘法分配律拆解,得\(a_y\times b_x<a_x\times b_y\)
所以一个排序函数就可以得到答案了。
代码实现
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
struct yyy{
int x,y;
}s[100039];
inline bool cmp(yyy x,yyy y){
return x.x*y.y<y.x*x.y;
}
long long ans,tot;
int main(){
register int i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&s[i].x);
for(i=1;i<=n;i++) scanf("%d",&s[i].y);
sort(s+1,s+n+1,cmp);
for(i=1;i<=n;i++){
ans+=s[i].x;
tot+=ans*s[i].y;
}
printf("%lld",tot);
return 0;
}
不过瘾?再来看一道
呵呵, 一看就是田忌赛马呀,只不过做两遍罢了。那么我们直接看代码......(笑)
首先如何让得分最大化。
回想一下田忌赛马,预备赛马的应该是一个有序组。所以我们先排一个序,满足
\(i<j<k\),\(a_i\geq a_j\geq a_k\).
然后应该考虑最强的两匹马。分类讨论。
命题一:若我方最强的马可以干掉对方最强的马,则直接干。
命题二:若我方最弱的马可以干掉对方最弱的马,则直接干
命题三:若命题一命题二都不成立,那么直接让我方最弱的马送给对方最强的马。
但在命题三中,我方最弱的马可能与对方最弱的马打平。所以要特判。
我方最低分则以对手最高分减去总分就可以了。
代码实现:
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a[100039],b[100039],ra,rb,la,lb,ans,flag;
int main() {
register int i;
scanf("%d",&n);
for(i=1; i<=n; i++) scanf("%d",&a[i]);
for(i=1; i<=n; i++) scanf("%d",&b[i]);
sort(a+1,a+n+1);
sort(b+1,b+n+1);
ra=rb=n;
la=lb=1;
for(i=1; i<=n; i++) {
if(a[ra]>b[rb])ra--,rb--,ans+=2;
else if(a[la]>b[lb])lb++,la++,ans+=2;
else {
if(a[la]==b[rb]) la++,rb--,ans++;
else la++,rb--; } }
printf("%d ",ans);
ra=rb=n;
la=lb=1;
ans=0;
for(i=1; i<=n; i++) {
if(a[ra]<b[rb])ra--,rb--,ans+=2;
else if(a[la]<b[lb])lb++,la++,ans+=2;
else {
if(a[ra]==b[lb]) lb++,ra--,ans++;
else lb++,ra--; } }
printf("%d",2*n-ans);
}