Codeforces 954 E. Water Taps
http://codeforces.com/problemset/problem/954/E
式子变成Σ xi*(ti-T)=0
sum0表示>=T的ai*ti之和
sum1表示<T的ai*ti之和
那么如果sum0<sum1,所有ti>=T的ai全加上
那么现在的Σ xi*(ti-T)>=0
考虑用ti<T的来使这个式子变成0,还要让Σ xi 最大
显然是选的ti与T的差距越小 ,xi可以用的越多
将ti从大到小排序后,以此选用,直到式子变成0
sum1<sum0 时 同理
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 200001 struct node { int a,t; }e[N],z[N],f[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool cmp1(node p,node q) { return p.t<q.t; } bool cmp2(node p,node q) { return p.t>q.t; } int main() { int n,T; read(n); read(T); for(int i=1;i<=n;++i) read(e[i].a); for(int i=1;i<=n;++i) read(e[i].t); int cntz=0,cntf=0; double sum0=0,sum1=0; int cnt0=0,cnt1=0; long long tot0=0,tot1=0;; for(int i=1;i<=n;++i) if(e[i].t>=T) { z[++cnt0]=e[i]; sum0+=1LL*e[i].a*(e[i].t-T); tot0+=e[i].a; } else { f[++cnt1]=e[i]; sum1+=1LL*e[i].a*(T-e[i].t); tot1+=e[i].a; } sort(z+1,z+cnt0+1,cmp1); sort(f+1,f+cnt1+1,cmp2); double ans=0; if(sum0>=sum1) { ans=tot1; for(int i=1;i<=cnt0;++i) if(1.0*z[i].a*(z[i].t-T)<=sum1) { sum1-=1.0*z[i].a*(z[i].t-T); ans+=z[i].a; } else { ans+=sum1/(z[i].t-T); break; } } else { ans=tot0; for(int i=1;i<=cnt1;++i) if(1.0*f[i].a*(T-f[i].t)<=sum0) { sum0-=1.0*f[i].a*(T-f[i].t); ans+=f[i].a; } else { ans+=sum0/(T-f[i].t); break; } } printf("%.8lf",ans); }