[Codeforces954E]Water Taps

本文介绍了一种解决特定数学优化问题的方法,通过调整变量并利用贪心策略找到目标函数的最大值。具体步骤包括数据预处理、排序、划分数组以及实现贪心选择。

题意

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


题解

先把titi减去TT,然后按照t排序

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

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

证明:

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

那么我们就可以把他们凑出一个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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值