题意:一张CD上有n首频率为f[i],长度为了l[i]的曲子,因为CD不能随机播放曲子,想播放第i首时,必须依次播放前i-1,
b[i]=f[i]*(a[1]+...+a[i]),sum=b[1]+..+b[n],求使sum最小的歌曲排列方式。
分析:因为1<=n<=2^16,时效只可能是O(nlogn)或O(n),
一开始以为是按频率排序,发现测试数据都过不了。
若已得到最优排列,使最优值为m
b[i+1]+b[i]=f[i+1]*l[i]+(f[i+1]+f[i])*(l[1]+...+l[i-1])+f[i+1]*l[i+1]+f[i]*l[i];
若交换
f[i]*l[i+1]+(f[i+1]+f[i])*(l[1]+...+l[i-1])+f[i+1]*l[i+1]+f[i]*l[i];
两个相减,res=f[i+1]*l[i]-f[i]*l[i+1];
i若res<0,通过交换取得m+res;
#include<cstdio> #include<algorithm> #define MAXN 100010 using namespace std; struct Song { int i; double l,f; }; Song s[MAXN]; bool Cmp(Song a, Song b) { return b.f*a.l-a.f*b.l<0; } int main() { int n,m,i,j,k; for(;scanf("%d",&n)+1;) { for(i=0;i<n;i++) scanf("%d%lf%lf",&s[i].i,&s[i].l,&s[i].f); scanf("%d",&m); sort(s,s+n,Cmp); printf("%d\n",s[m-1].i); } return 0;