2017-9-3 校内模拟T2取数win
题意:给你一个序列,叫你找一个子序列,使得这个子序列的平均数减去中位数最大。
思路:题面直接说是单峰函数,我也没多想(根本没看懂),现在看来就是排序+三分搜索啦。
代码:(特地去学了下三分。。):
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; int n; long long lefts,rights,lm,mr; int num[200100],presum[200100]; double ansx,anss,ans,hh=-1; double df(long long w,long long l){ long long k=presum[w]-presum[w-l-1]+presum[n]-presum[n-l]; return (double)k/(double)(2*l+1)-(double)num[w]; } int main(){ //freopen("win.in","r",stdin); //freopen("win.out","w",stdout); scanf("%d",&n); if(n<3){ printf("0.00\n"); return 0; } for (int i=1;i<=n;i++) scanf("%d",&num[i]); presum[0]=1; sort(num+1,num+n+1); for (int i=1;i<=n;i++) presum[i]=presum[i-1]+num[i]; for (int i=1;i<=n;i++){ lefts=0; rights=min(n-1,i-1); while(lefts<rights){ lm=(rights-lefts)/3+lefts; mr=rights-(rights-lefts)/3; ansx=df(i,lm);anss=df(i,mr); if(ansx>anss) rights=mr-1; else lefts=lm+1; } ans=df(i,lefts); if(ans>hh) hh=ans; } printf("%.2lf\n",hh); return 0; }