题面传送门
贪心一般和排序逃不开关系。这一道题目是普及组原题的弱化版。
首先我们列出答案的式子
a
n
s
=
∑
i
=
1
n
(
a
i
×
∑
j
=
1
i
b
j
)
ans=\sum\limits_{i=1}^{n}{(a_i\times\sum\limits_{j=1}^{i}{b_j})}
ans=i=1∑n(ai×j=1∑ibj)
乘法分配律,
a
n
s
=
∑
i
=
1
n
(
a
i
×
b
i
+
a
i
×
∑
j
=
1
i
−
1
b
j
)
ans=\sum\limits_{i=1}^{n}{(a_i\times b_i+a_i\times \sum\limits_{j=1}^{i-1}{b_j})}
ans=i=1∑n(ai×bi+ai×j=1∑i−1bj)
分配到每一个
s
i
s_i
si,得
s
i
=
a
i
×
b
i
+
a
i
×
∑
j
=
1
i
−
1
b
j
s_i=a_i\times b_i+a_i\times \sum\limits_{j=1}^{i-1}{b_j}
si=ai×bi+ai×j=1∑i−1bj
若要比较两个
a
x
a_x
ax与
a
y
a_y
ay的优先级关系,得
a
x
×
b
x
+
a
x
×
∑
j
=
1
x
−
1
b
j
+
a
y
×
b
y
+
a
y
×
∑
j
=
1
y
−
1
b
j
<
a
y
×
b
y
+
a
y
×
∑
j
=
1
y
−
1
b
j
+
a
x
×
b
x
+
a
x
×
∑
j
=
1
x
−
1
b
j
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}
ax×bx+ax×j=1∑x−1bj+ay×by+ay×j=1∑y−1bj<ay×by+ay×j=1∑y−1bj+ax×bx+ax×j=1∑x−1bj
两边同时消去,得
a
x
×
∑
j
=
1
x
−
1
b
j
+
a
y
×
∑
j
y
−
1
b
j
<
a
y
×
∑
j
=
1
y
−
1
b
j
+
a
x
×
∑
j
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}
ax×j=1∑x−1bj+ay×j∑y−1bj<ay×j=1∑y−1bj+ax×j∑x−1bj
再由于
y
=
x
+
1
y=x+1
y=x+1,进行乘法分配律拆解,得
a
y
×
b
x
<
a
x
×
b
y
a_y\times b_x<a_x\times b_y
ay×bx<ax×by
所以一个排序函数就可以得到答案了。
代码实现
#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
i<j<k
i<j<k,
a
i
≥
a
j
≥
a
k
a_i\geq a_j\geq a_k
ai≥aj≥ak.
然后应该考虑最强的两匹马。分类讨论。
命题一:若我方最强的马可以干掉对方最强的马,则直接干。
命题二:若我方最弱的马可以干掉对方最弱的马,则直接干
命题三:若命题一命题二都不成立,那么直接让我方最弱的马送给对方最强的马。
但在命题三中,我方最弱的马可能与对方最弱的马打平。所以要特判。
我方最低分则以对手最高分减去总分就可以了。
代码实现:
#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);
}