玄学的实数比较
查看原帖
玄学的实数比较
307453
云浅知处はなび楼主2020/7/3 17:16

看到题后,直接写了个代码:

大概是用 ST表 O(nlogn)O(n\log n) 预处理最小值,用前缀和数组 ss 搞前缀和,那么后 xx 个数的和就是 snsnx1s_n-s_{n-x-1}

然后后面就没啥了......

我知道我这代码有很多可以改进的地方,比如不开 ST表 直接维护后 nn 个数的最小值,不开一个专门的数组k来存答案,不过应该都不影响......

代码如下:

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>

using namespace std;

#define MAXN 100005

int a[MAXN],s[MAXN],n;
int ST[MAXN][50];

struct node{
    int num;
    double ans;
}k[MAXN];

void inp(){
    
    scanf("%d",&n);
    
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        s[i]=a[i]+s[i-1];
        ST[i][0]=a[i];
    }

}

void pre(){
    for(int i=1;(1<<i)<=n;i++){
        for(int j=1;j+(1<<i)-1<=n;j++){
            ST[j][i]=min(ST[j][i-1],ST[j+(1<<(i-1))][i-1]);
        }
    }
}

bool cmp(node p,node q){
    return (p.ans==q.ans)?p.num<q.num:p.ans>q.ans;
}

int query(int l,int r){
    int lg=log2(r-l+1);
    return min(ST[l][lg],ST[r-(1<<lg)][lg]);
}

int main(void){
    
    inp();

    pre();

    for(int i=0;i<=n;i++){
        if(n==i||n==i+1){
            k[i].num=i,k[i].ans=0;
            break;
        }
        double tmp=(double)(s[n]-s[i]-query(i+1,n))/(n-i-1);
        k[i].num=i;
        k[i].ans=tmp;
    }

    sort(k,k+n+1,cmp);

    int tmp=k[0].ans;
    for(int i=0;i<=n;i++){
        if(k[i].ans==tmp){
            printf("%d ",k[i].num);
        }
        else{
            break;
        }
    }

    return 0;
}

在 WA 多次仍不明所以之后,我下载测试点,然后手写了一个print()函数,直接输出了k[]s[]的每一个元素,如下:

void print(){
    for(int i=1;i<=n;i++){
        printf("%d ",s[i]);
    }
    puts("");
    for(int i=0;i<=n;i++){
        printf("%d %d %lf\n",i,k[i].num,k[i].ans);
    }
}

结果发现我这代码答案是对的,只不过浮点数的比较炸了......

然后看了看题解区大佬的做法,好像要设置精度啥的,于是设了个精度eps=1e-6

修改之后输出函数就成了这样:

    for(int i=0;i<=n;i++){
        if(fabs(k[i].ans-tmp)<eps/*上面已经#define eps 1e-6*/){
            printf("%d ",k[i].num);
        }
        else{
            break;
        }
    }

但是,一样的还是错了......

求大佬帮个忙!QwQ

2020/7/3 17:16
加载中...