题目链接:https://codeforces.com/contest/1300/problem/E
题目大意:
有一个区间,每次可以给出L,R,然后会将L~R区间内的所有数字替换成这个区间的平均数,求这个区间所能形成的字典序最小的区间
题目思路:
卿学姐说这道题唯一的难点就在于复杂度的计算,深以为然…被D题计算几何吓坏的我,对于E看了一眼,区间操作,字典序,又是E题,就灰溜溜的跑了,当时没细想,但也确实想到了应该让尽可能靠前的小就行,但是想到这是E题,就没多想,感觉肯定没那么简单。。。结果。。。。。。就是存一个num数组和p数组,然后把这个序列分成一个又一个块,比如遇到2 1,2是一个块,1又是一个,这个时候发现1这个块比2这个块要小,所以为了让前面尽可能小,就让这个块和前一个块合并,合并后的结果再跟前面那个合并。乍看这好像是 n 2 n^2 n2复杂度,但是胖友们,仔细想想,每个人想当块代表只有一次的殊荣!如果你比被合并了那就直接人没了,没有下次冒泡的机会了,每个人只有一次当块的机会!这是O(n)的!具体怎么做看代码就能秒懂,非常简单,主要就是被它是E题吓到了,以后面对什么题都不要怕,微笑着面对他,坚持就是胜利,加油奥利给!
以下是代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,a,b) for(ll i=a;i<=b;i++)
#define per(i,a,b) for(ll i=a;i>=b;i--)
const int MAXN = 1e6+5;
int n,num[MAXN];
double a[MAXN],p[MAXN];
int main()
{
int n;
while(~scanf("%d",&n)){
int pos=0;
rep(i,1,n){
scanf("%lf",&a[i]);
p[++pos]=a[i],num[pos]=1;
while(pos>1&&p[pos-1]>p[pos]){
p[pos-1]=(p[pos-1]*num[pos-1]+p[pos]*num[pos])/(num[pos-1]+num[pos]);
num[pos-1]+=num[pos];
pos--;
}
}
rep(i,1,pos){
rep(j,1,num[i])printf("%.10lf\n",p[i]);
}
}
return 0;
}