MnZn求助精度
查看原帖
MnZn求助精度
455490
Sharpsmile楼主2022/6/20 17:05

%你赛的题,模拟赛的时候开数组没算高精度小数类直接开炸了,暴力的60挂没了

去题解里学了个斜优的做法,但是只有73,错的都是只保证误差小于1e-5,个人猜测可能是中间斜优算策略的时候精度挂了,但是看了半天觉得精度又没啥问题。

各位大佬快来帮帮我哇QAQ ,赶紧改完这题就可以去改那个把O看成0挂46分的旷野大计算了

代码如下。


struct node{
    double x,y;
    friend node operator-(const node x,const node y){
        return {x.x-y.x,x.y-y.y};
    }
    friend double operator *(const node x,const node y){
        return x.x*y.y-x.y*y.x;
    }
};
double v[8200],sum[8200];
double dp[2][8200];
int pre[8200][8200];
int n,k,p;
Decimal ANS;
deque<node>q;
inline void ok(int k,int loc,Decimal &x){
    if(!k)return ;
    ok(k-1,pre[k][loc],x);
    x=(x+sum[loc]-sum[pre[k][loc]])/(loc-pre[k][loc]+1);
}
signed main(){
    ios::sync_with_stdio(false);
    cin>>n>>k>>p;
    for(int i=1;i<=n;i++)cin>>v[i];
    Decimal op=to_string(v[1]);
    double opt=v[1];
    sort(v+1,v+n+1);
    int loc=n+1;
    for(int i=1;i<=n;i++)
        if(v[i]>opt){loc=i;
            break;
        }
    for(int i=loc;i<=n;i++)
        v[i-loc+1]=v[i]-opt;;
    n=n-loc+1;
    k=min(k,n);
        bool fl=1;
        double nowAs=0;
        int sk=0;
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+v[i];
        for(int i=1;i<=k;i++){
            q.clear();
            q.push_back({(double)(i-2),(double)(sum[i-1]-dp[!fl][i-1])});
            for(int j=i;j<=n;j++){
                node A={(double)(j),(double)(sum[j])};
                while(q.size()>=2&&(A-q[0])*(A-q[1])>0)q.pop_front();
                dp[fl][j]=(A-q.front()).y/(A-q.front()).x;
                pre[i][j]=q.front().x+1;
                node P={(double)(j-1),(double)(sum[j]-dp[!fl][j])};
                while(q.size()>=2&&(P-q[q.size()-2])*(q[q.size()-1]-q[q.size()-2])>0)q.pop_back();
                q.push_back(P);
            }
            if(nowAs<dp[fl][n])nowAs=dp[fl][n],sk=i;
            fl^=1;
        }
        ok(sk,n,ANS);
        op+=ANS;
    cout<<op.to_string(p<<1);
2022/6/20 17:05
加载中...