[Codeforces954E]Water Taps

题意

xi[1,ai], ∀ x i ∈ [ 1 , a i ] , 对于所有满足 ni=1xi(tiT)=0 ∑ i = 1 n x i ( t i − T ) = 0 的情况,求 ni=1xi ∑ i = 1 n x i 的最大值


题解

先把 ti t i 减去 T T ,然后按照t排序

把数组分成两块,一半小于等于 0 0 ,一半大于0

用贪心的思想,可以发现有一半必须全选,另一半选最靠近 T T 的那些

证明:

假设负数集里面还有一些没选,正数集里还有数剩余

那么我们就可以把他们凑出一个0出来,直到某一边用完为止.证毕.

后半句话是显然的...

所以就可以直接贪心了

#include<bits/stdc++.h>
#define fp(i,a,b) for(int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){if(A==B){B=(A=ss)+fread(ss,1,1<<17,stdin);if(A==B)return EOF;}return*A++;}
template<class T>inline void sd(T&x){
    char c;T y=1;while(c=gc(),c<48||57<c)if(c=='-')y=-1;x=c^48;
    while(c=gc(),47<c&&c<58)x=(x<<1)+(x<<3)+(c^48);x*=y;
}
const int N=2e5+5;
const double eps=1e-8;
typedef int arr[N];
int n,T;double tp,ans;
struct da{int a,t;double s;}a[N];
inline bool cmp(da a,da b){return a.t<b.t;}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n);sd(T);
    fp(i,1,n)sd(a[i].a);fp(i,1,n)sd(a[i].t),a[i].t-=T;
    sort(a+1,a+n+1,cmp);
    if(a[1].t>0||a[n].t<0)return puts("0"),0;
    fp(i,1,n)a[i].s=(double)a[i].a*a[i].t,tp+=a[i].s;
    if(tp<0){fp(i,1,n)a[i].t=-a[i].t,a[i].s=-a[i].s;reverse(a+1,a+n+1);}
    tp=0;
    fp(i,1,n){
        if(tp+a[i].s>0){ans+=(-tp)/a[i].t;break;}
        tp+=a[i].s,ans+=a[i].a;
    }
    printf("%.6lf",ans);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值