Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Solution
尝试不同的姿势ing~(才不会告诉你们之前拿值域线段树强上失败的故事)
这次是替罪羊树,很暴力很暴力~
估价用的是
log1a(size)<height
#include<stdio.h>
#include<algorithm>
#include<cmath>
#define N 100005
using namespace std;
const double D=log(1/0.75);
int a,rc,rn,cc,ans,op,root,tot,loc[N],num[N],u,n;
struct poi{int a,f,l,r,s,h;}t[N];
void insert(int &k,int fa)
{
if (!k){t[k=++tot]={a,fa,0,0,1,1};return;}
if (abs(t[k].a-a)<abs(ans-a)) ans=t[k].a;
if (a<=t[k].a)
{
insert(t[k].l,k);
if (t[k].l==tot) for (int K=t[k].r;K;K=t[K].l) if (abs(t[K].a-a)<abs(ans-a)) ans=t[K].a;
}
else
{
insert(t[k].r,k);
if (t[k].r==tot) for (int K=t[k].l;K;K=t[K].r) if (abs(t[K].a-a)<abs(ans-a)) ans=t[K].a;
}
t[k].s++;
t[k].h=max(t[t[k].l].h,t[t[k].r].h)+1;
if (log(t[k].s)/D<t[k].h) cc=k;
}
void dfs(const int &k)
{
if (!k) return;
loc[++rc]=k;
dfs(t[k].l);
num[++rn]=t[k].a;
dfs(t[k].r);
}
void build(int &k,const int &fa,const int &l,const int &r)
{
if (r<l) return;
int mid=l+r>>1;
t[k=loc[++u]]={num[mid],fa,0,0,r-l+1,0};
build(t[k].l,k,l,mid-1);
build(t[k].r,k,mid+1,r);
t[k].h=max(t[t[k].l].h,t[t[k].r].h)+1;
}
inline void rebuild(int &c)
{
rc=rn=u=0;
dfs(c);
int K=t[c].f;
build(t[K].l==c?t[K].l:t[K].r,K,1,rc);
for (;K;K=t[K].f) t[K].h=max(t[t[K].l].h,t[t[K].r].h)+1;
c=0;
}
int main()
{
scanf("%d",&n);
scanf("%d",&a);
t[0]={0,0,1,1,0,0};
t[root=tot=1]={op=a,0,0,0,1,1};
for (int i=1;i<n;i++)
{
scanf("%d",&a);ans=233333333;
insert(root,0);
op+=abs(ans-a);
if (cc) rebuild(cc);
}
printf("%d\n",op);
}