题意:要使损失降到最小,求出被摧残的最小的花数。
考察:
贪心(套路,经典题)
思路:
类似国王游戏那道题。交换相邻两头牛的顺序既不影响前面的牛破坏的花的数量
也不影响后面的牛破坏的花的数量。
首先构造
2a[i].tb[i].d<2a[i].db[i].t的情况,即先抱走a使结果最优的情况。
两边同时除以2a[i].db[i].d
得到a[i].t/a[i].d<b[i].t/b[i].d
设rate= a[i].t/a[i].d,只与自身有关。
显然rate越小的放前面更优。
因此按rate从小到大对序列排序。
然后就是算被被摧残的花的最小数目了。
先求出摧残的花的数目的前缀和。
由题意得,当第a[i]头牛被抱走时,后面得所有牛都有
2*a[i].t得2时间去摧残花花。
所以ans+=(sum[n]-sum[i])2a[i].t
注意数据范围,ans用ll
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
struct node{
int t,d;
double rate;
bool operator<(const node& x) const{
return rate<x.rate;
}
}a[N];
int sum[N];
ll ans;
int main(){
int n;
scanf("%d",&n);
/*
a[i].t*b[i].d<a[i].d*b[i].t
a[i].t/a[i].d<b[i].t/b[i].d
*/
for(int i=1;i<=n;i++){
//时间和摧残的花花
scanf("%d%d",&a[i].t,&a[i].d);
a[i].rate=1.0*a[i].t/a[i].d;//这个越小放前面
}
sort(a+1,a+n+1);//排序
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].d;//前缀和,前面的牛摧残的花总数
}
for(int i=1;i<=n;i++){
ans+=(sum[n]-sum[i])*2*a[i].t;// a[i]这头牛被抱走了,剩下后面的所有的牛都有2*a[i].t的时间去摧残花花
}
printf("%lld\n",ans);
return 0;
}