题目链接
题意给你n个数,给你一种操作你可以选择一个区间,然后把这个区间的数变为(区间和)/(区间长度),之后让你求多次操作后字典序最小的数组a
解法:
1.如果当前的数字的数都是升序的,那么当前一定是字典序最小的,不需要操作直接输出.
2.有一种类似andrew求凸包的方法,我们一开始维护出一个前缀和,之后我们求出1-n之间中,求出操作[l, r]能够使得a[l]变小的左端点l,最后在队列对答案进行求出即可
#include#define M 200009 #define ll long long #define ls u<<1 #define rs u<<1|1 #define sc scanf #define pr printf using namespace std; const int maxn = 1e6 + 7; double a[maxn]; int q[maxn],pos; int n; bool is_sort(){ for(int i = 2; i <= n; i++){ if(a[i] >= a[i - 1])continue; else return false; } return true; } double across(int i , int j, int k){ return (j - i)*(a[k] - a[i]) - (k - i)*(a[j] - a[i]); } int main(){ sc("%d",&n); for(int i = 1; i <= n; i++)sc("%lf",&a[i]); if(is_sort()){ for(int i = 1; i <= n; i++){ if(i == 1)pr("%.9lf",a[i]); else pr(" %.9lf",a[i]); } }else{ for(int i = 1; i <= n; i++)a[i] += a[i - 1]; for(int i = 0; i <= n; i++){ while(pos > 1 && across(q[pos - 2], q[pos - 1], i) <= 0) pos -- ; q[pos++] = i; } for(int i = 1; i < pos; i++){ int len = q[i] - q[i - 1]; double res = (double)(a[q[i]] - a[q[i - 1]])/len; while(len--){ pr("%.9lf ",res); } } } }



