思維
#include<bits/stdc++.h>
#define pk push_back
using namespace std;
typedef long long ll;
double dp[1000010],sum[1000010];
int main()
{
int n,x;
cin>>n;
for(int i=1;i<=n;i++)
cin>>x,dp[i]=x,sum[i]=sum[i-1]+dp[i];//前綴和 便於計算區間和
for(int i=2;i<=n;i++)
{
double cnt=dp[i];
for(int j=i-1;j>=1;j--) //找到一個 低點
{
if(dp[j]>cnt)
{
cnt=(sum[i]-sum[j-1])/(i-j+1); 新區間平均值
if(j==1)
for(int k=j;k<=i;k++)
dp[k]=cnt; //區間更新
}
else
{
for(int k=j+1;k<=i;k++)
dp[k]=cnt; // 區間更新
break;
}
}
}
for(int i=1;i<=n;i++)
printf("%.9lf\n",dp[i]);
return 0;
}
上面的代碼妥妥TLE 所以我可以可以優化 區間更新和查找低點的過程
如下
#include<bits/stdc++.h>
#define pk push_back
using namespace std;
typedef long long ll;
double sum[1000010];
int x[1000010];
struct node
{
int l,r; // 區間[l,r]
double w; //區間平均值
};
vector<node> a; // 任意一個線性結構
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>x[i],sum[i]=sum[i-1]+(double)x[i];
a.pk((node){1,1,(double)x[1]});
for(int i=2;i<=n;i++)
{
double cnt=(double)x[i];
int l=i;
for(int j=a.size()-1;j>=0;j--)
{
if(a[j].w>=cnt)
{
l=a[j].l;
cnt=(sum[i]-sum[l-1])/(i-l+1);
a.pop_back(); // 當前節點刪去
if(j==0)
{
a.pk((node){1,i,cnt}); // 新區間更新 變成了更新一個節點
break;
}
}
else
{
a.pk((node){l,i,cnt});
break;
}
}
}
for(int i=0;i<a.size();i++)
{
for(int j=a[i].l;j<=a[i].r;j++)
printf("%.9lf\n",a[i].w); 輸出區間
}
a.clear();
return 0;
}