Codeforces Round #618 (Div. 2) E. Water Balance(贪心)

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/toohandsomeIeaseId/article/details/104252733