题目
给你一个数列
,每次选择一段区间
,将其中每个数变为他们的平均数,问最小字典序?
思路
TM傻逼题
发现
前的操作不会改变
前缀和 ,记前缀和为
,一次修改操作相当于将
将
看成点后,这TM不就是两点连线吗
求字典序最小然后就是维护一个下凸壳,单调栈即可(不会的学学斜率优化)
代码
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstring>
#include<climits>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
inline int read() {
bool f=0;int x=0;char c=getchar();
while(c<'0'||'9'<c){if(c==EOF)exit(0);if(c=='-')f=1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return !f?x:-x;
}
#define eps 1e-10
#define MAXN 1000000
#define INF 0x3f3f3f3f
double p[MAXN+5];
int Stk[MAXN+5],tp;
int main(){
int n=read();
for(int i=1;i<=n;i++)
p[i]=p[i-1]+read();
Stk[++tp]=0;
for(int i=1;i<=n;i++){
while(tp>=2&&(p[i]-p[Stk[tp]])/(i-Stk[tp])<(p[i]-p[Stk[tp-1]])/(i-Stk[tp-1]))
tp--;
Stk[++tp]=i;
}
for(int i=2;i<=tp;i++){
double tmp=(p[Stk[i]]-p[Stk[i-1]])/(Stk[i]-Stk[i-1]);
for(int j=Stk[i-1]+1;j<=Stk[i];j++)
printf("%.10lf\n",tmp);
}
return 0;
}
反省
一定要多寻找题目特殊点,考试不要慌(老毛病又犯了)