看到题后,直接写了个代码:
大概是用 ST表 O(nlogn) 预处理最小值,用前缀和数组 s 搞前缀和,那么后 x 个数的和就是 sn−sn−x−1。
然后后面就没啥了......
我知道我这代码有很多可以改进的地方,比如不开 ST表 直接维护后 n 个数的最小值,不开一个专门的数组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